0

i would like to create a nested list of arbitrary depth (containing numerical values specifically) with uniform arbitrary lengths at each level and then compress it to a NumPy array of minimum dimensions ie. if a layer of lists all length 1 all lists at that depth are unpacked.

example:


import random as ran
import numpy as np

prompt = (3,1,5,1)
#promt length and positions of 1 should be arbitrarily
old_list = []

for a in range(prompt[0]):
    old_list.append([])
    for b in range(prompt[1]):
        old_list[a].append([])
        for c in range(prompt[2]):
            old_list[a][b].append([])
            for d in range(prompt[3]):
                #using random outputs for simplicity, could be anything 
                old_list[a][b][c].append(ran.randint(0, 10))

new_list = []
for a in range(prompt[0]):
    new_list.append([])
    #prompt[1] should be automatically skipped as it is 1 
    for c in range(prompt[2]):
        #prompt[3] should be automatically skipped as it is 1 
        new_list[a].append(old_list[a][0][c][0])
final = np.array(new_list)

print(f'''{final} 
          is clearly and more useful and tidier than
          {old_list} ''')

I expect there is some way of automating for loops in the manner described, and compacting them as well, in NumPy, but I don't Know where to get started. any help would be apreciated. thankyou!

5
  • 1
    You can used this np.random.randint(0, 10, size=prompt) Commented Aug 6 at 16:21
  • You could use np.reshape for "compacting". np.array(old_list).reshape(3, 5) would give you a similar result. Commented Aug 6 at 16:28
  • 1
    @Adeva1 you mean np.array(old_list).reshape([v for v in prompt if v!= 1]) without knowing the values in prompt but just wanting to flat list of 1 element Commented Aug 6 at 16:35
  • np.squeeze removes size 1 dimensions. Commented Aug 6 at 19:41
  • 1
    Creating the array directly will be faster and easier, unless the element assignment function is a harder to use than 'random'. Think multidimensional array from the start rather than nested lists. Commented Aug 6 at 19:46

1 Answer 1

1

If your goal is to have a numpy array, you do not need to generate an intermediate python object with nested lists. It's much faster and memory efficient to directly create a random numpy array (e.g. with np.random.randint).

If you want to remove the axes of length 1, squeeze:

prompt = (3, 1, 5, 1)
final = np.random.randint(0, 10, size=prompt).squeeze()

Or, with the new Generator interface:

prompt = (3, 1, 5, 1)
rng = np.random.default_rng()
final = rng.integers(0, 10, size=prompt).squeeze()

Example output:

array([[2, 1, 1, 7, 5],
       [0, 4, 1, 1, 6],
       [6, 0, 2, 3, 7]])

Now, if you really want a pure python approach, you could go with a recursive function:

import random

def nested_list(prompt, squeeze=True):
    if not prompt:
        return []
    if squeeze:
        prompt = [i for i in prompt if i != 1] or [1]
    i, *prompt = prompt
    if prompt:
        return [nested_list(prompt, squeeze=False) for _ in range(i)]
    else:
        return [random.randint(0, 10) for _ in range(i)]

nested_list((3, 1, 5, 1))
# [[9, 3, 1, 4, 6], [2, 9, 10, 0, 8], [1, 6, 8, 9, 10]]

nested_list((3, 1, 5, 1), squeeze=False)
# [[[[8], [10], [8], [7], [6]]],
#  [[[10], [8], [7], [1], [1]]],
#  [[[0], [10], [5], [7], [0]]]]

nested_list((1, 1, 1))
# [9]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.