简体   繁体   中英

Preventing nested list output from a for-loop / list comprehension when appending new values to an Array

I am trying to loop over a list comprehension where the output ('my_array') is being iterated over in the list comprehension:

my_array = np.linspace(1, 8, 10)
harmonic = np.random.rand(10,4)
var1 = (11, 12, 13, 14)
for coeff in range(4):
    my_array = [my_array + harmonic[coeff] * var1]

While this appears to work, my_list ends up being nested within 4 other lists and an array:

[array([[[[ val1, val2, ...]]]])]

I have two questions:

  1. Can I accomplish the above without getting a deeply nested list as a result?
  2. Should I just give up on the list comprehension and use two for loops instead (for the sake of improved readability)?

UPDATE: I wasn't being clear enough in my original post to convey the issue I've been having. The original code snippet is too simplistic for the actual case. harmonic is a 10x4 array in this example, var1 is a 4 element tuple that has been yanked from a dictionary, and my_array (previously my_list ) is a 10 element array. I would like to multiply the first column in harmonic with the first element in var1 , the second column of harmonic with the second element of var1 , and so on. I would then like to add these 4 columns and my_array together.

I used Pacific Stickler's solution 1 with a small variation, to account for the more complex variables:
product = harmonic * var1
new_array = my_array + np.sum(product, axis=1)

Confusion:

Your problem statement seems unclear because of:

  1. your mentioning of list comprehension but not using it
  2. your usage of confusing / specialized names for variables in a toy problem which should have simple non-conflicting dummy names
  3. absence of the desired output given some dummy values of the variables
  4. unclear goal of either adding or concatenating the values to your existing array

First, let's Get Your Problem Straight:

You have:

  1. a numpy array called my_list
  2. a list called harmonic
  3. a variable called var1

You want to either:

  1. add to my_list element-wise the sum of the first 4 values of harmonic after each has been scaled by var1 OR
  2. append to my_list the first 4 values of harmonic after they have been scaled by var1

Assume dummy values for harmonic and var1 :

harmonic = np.arange(4)
var1 = 2

Solution:

For the 1st goal:

You don't need to use either a list comprehension or a nested for loop :

  1. you can multiply element-wise var1 with harmonic and then use np.sum() to add all of its elements
  2. you can then add element-wise the result from step 1 to my_list

Remember: scalar operations are always element-wise in numpy

>>> my_list + np.sum( harmonic * var1 )
array([ 13.        ,  13.77777778,  14.55555556,  15.33333333,
    16.11111111,  16.88888889,  17.66666667,  18.44444444,
    19.22222222,  20.        ])

For the 2nd goal:

  1. You can again element-wise multiply var1 with harmonic OR use list comprehension to loop over first 4 values of harmonic and form a new list of modified values.
  2. Then use np.append() to concatenate the newly formed list to your my_list .

ie

>>> np.append( my_list, var1 * harmonic ) 
# equivalent to: np.append( my_list, [harmonic[i] * var1 for i in range(4)])
array([ 1.        ,  1.77777778,  2.55555556,  3.33333333,  4.11111111,
        4.88888889,  5.66666667,  6.44444444,  7.22222222,  8.        ,
        0.        ,  2.        ,  4.        ,  6.        ])

Your Incorrect Approach:

Your code tries to form a list using list comprehension by forming a new numpy array at each iteration by adding the modified elements of harmonic element-wise to your old my_list and concatenating this newly formed numpy array to your list at each iteration.

So your approach is equivalent to the following:

>>> my_list = [my_list + harmonic[i] * var1 for i in range(4)]

which offcourse gives you a ( nested ) list of numpy arrays:

[array([ 1.        ,  1.77777778,  2.55555556,  3.33333333,  4.11111111,
         4.88888889,  5.66666667,  6.44444444,  7.22222222,  8.        ]), array([  3.        ,   3.77777778,   4.55555556,   5.33333333,
         6.11111111,   6.88888889,   7.66666667,   8.44444444,
         9.22222222,  10.        ]), array([  5.        ,   5.77777778,   6.55555556,   7.33333333,
         8.11111111,   8.88888889,   9.66666667,  10.44444444,
        11.22222222,  12.        ]), array([  7.        ,   7.77777778,   8.55555556,   9.33333333,
        10.11111111,  10.88888889,  11.66666667,  12.44444444,
        13.22222222,  14.        ])]

Note that you're not actually using a list comprehension in this code. You could, if you wanted. Try this instead:

my_list = range(10) + [cycle[coeff] * var1 for coeff in range(4)]
# in python3, you'll have to do ... = list(range(10)) + ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM