Home > other >  How to replace values in nested array with values from a list?
How to replace values in nested array with values from a list?

Time:06-12

Consider the variable "A" and an array with several nested arrays. Both "A" and the nested arrays contain the same amount of elements, in this case 5. Each nested array are also nested together in groups of 3.

A=[10,20,30,40,50]
array=[[[1,5,8,3,4],[18,4,-8,4,21],[-8,12,42,16,-9]], ...]

I was wondering how I can replace the elements in each nested array with the corresponding elements in A if the value of the element in the nested array exceeds a certain threshold. Otherwise, if the element fails to exceed the threshold, replace with zero.

For example, if the threshold is 10 in this example, the result would be:

array=[[[0,0,0,0,0],[10,0,0,0,50],[0,20,30,40,0]], ...]

I know this might be a simple problem, but I'm having trouble comprehending multidimensional arrays, especially if they are greater than 2-dimensions. The bigger question is, how would I do this if those arrays are nested under many arrays without using several for loops? My incorrect attempt:

for a in array:
   for x in a:
      for i in x:
         if a[i]>10:
            a[i]=A[i]
         else:
            a[i]=0

CodePudding user response:

Your attempt is not working because first of all you are using the list value i as an index. In the line for i in x: the variable i will take each value of the list x, and if you need the index of it as well, you can use for id, i in enumerate(x) which gives you each value of the list as i and its index as id.

Moreover, to update the array, it is not enough to update x inside the loop, you need to update the array directly. And of course you can use list comprehension for simplicity in the last loop. So a solution to your problem could look like this:

for i1, val1 in enumerate(array):
    for i2, val2 in enumerate(val1):
        array[i1][i2] = [y if x>10 else 0 for (x, y) in zip(val2, A)]

As for your bigger question, the general solution when you have multiple nested lists and you don't want to use for loops is to implement recursive functions.

Here, one recursive solution to your problem would be:

def my_recursive_fun(input):
    if isinstance(input, list) and isinstance(input[0], list):
        return [my_recursive_fun(item) for item in input]
    else:
        return [y if x>10 else 0 for (x, y) in zip(input, [10,20,30,40,50])]

array=[[[1,5,8,3,4],[18,4,-8,4,21],[-8,12,42,16,-9]]]
new_array = my_recursive_fun(array)

The good thing about recursive solution is that it works with any number of nested lists (of course there are limits) without changing the code.

CodePudding user response:

If the nesting of your array is arbitrary deep, then go for a recursive function:

def apply_threshold(substitutes, limit, source):
    if isinstance(source[0], list):  # recursive case
        return [apply_threshold(substitutes, limit, elem) for elem in source]
    else:  # base case
        return [subst if value >= limit else 0 
                for subst, value in zip(substitutes, source)]

Here is how to use it:

A = [10,20,30,40,50]
array = [[[1,5,8,3,4],[18,4,-8,4,21],[-8,12,42,16,-9]]]
result = apply_threshold(A, 10, array)
print(result)  # [[[0, 0, 0, 0, 0], [10, 0, 0, 0, 50], [0, 20, 30, 40, 0]]]
  • Related