Home > Net >  replace numbers from one list to another
replace numbers from one list to another

Time:10-18

strong text I have matrix (3-d array)

strong text "a" and "b" shape: (5, 3, depths), depths == can varaible, in this example is 2, but sometimes could be 3 or 4 or 6, I am looking for a function that works with different depths.

Blockquote a= [[[10,15,10,9,45], [2,21,78,14,96], [2,2,78,14,96], [3,34,52,87,21], [52,14,45,85,74] ], [[52,14,45,85,74], [2,2,78,14,96], [15,41,48,48,74], [3,34,52,87,21], [14,71,84,85,41]]]

Blockquote b= [[[0,1,0,1,1], [2,2,1,0,0], [2,2,1,1,0], [0,0,0,0,1], [0,0,1,1,1] ], [[0,0,0,1,1], [0,1,1,1,2], [2,2,2,2,0], [0,0,0,1,1], [1,0,0,0,1]]]

strong text I want a matrix "c", "c" should be the copy of "a", but when a value in "b" is == 0, "c" will also be == 0

Blockquote c= [[[0,15,0,9,45], [2,21,78,0,0], [2,21,78,14,0], [0,0,0,0,21], [0,0,45,85,74] ], [[0,0,0,85,74], [0,2,78,14,96], [15,41,48,48,0], [0,0,0,87,21], [14,0,0,0,41]]]

strong text

thank for yourl help

CodePudding user response:

Use numpy arrays and element-wise multiplication:

import numpy as np

a= [[[10,15,10,9,45], [2,21,78,14,96], [2,2,78,14,96], [3,34,52,87,21], [52,14,45,85,74] ], [[52,14,45,85,74], [2,2,78,14,96], [15,41,48,48,74], [3,34,52,87,21], [14,71,84,85,41]]]
b= [[[0,1,0,1,1], [2,2,1,0,0], [2,2,1,1,0], [0,0,0,0,1], [0,0,1,1,1] ], [[0,0,0,1,1], [0,1,1,1,2], [2,2,2,2,0], [0,0,0,1,1], [1,0,0,0,1]]]

result = np.array(a) * np.array(b)
result = result.tolist()   # if you want the final result as a list
print(result)
[[[0, 15, 0, 9, 45], [4, 42, 78, 0, 0], [4, 4, 78, 14, 0], [0, 0, 0, 0, 21], [0, 0, 45, 85, 74]], [[0, 0, 0, 85, 74], [0, 2, 78, 14, 192], [30, 82, 96, 96, 0], [0, 0, 0, 87, 21], [14, 0, 0, 0, 41]]]

CodePudding user response:

Note : In the question, you are talking about 5x3 blocks, but your example is 5x5. i'll assume the correct format is 5x5xDepth

Without using numpy

Let's define our depth and a result blockquote

depth = len(a)
result = []

So we can iterate trought our blockquote :

for x in range(depth):
   # This is a 5 x 5 array
   2d_block = []
   for y in range(5):

       # This is our final dimension, array of lengh 5
       1d_block = []
       for z in range(5):
           # Check if b is 0
           if b[x][y][z] == 0:
                1d_block.append(0)
           else:
                1d_block.append(a[x][y][z])
        # Add our block to the current 2D block
        2d_block.append(1d_block) 
        
    # Add our blocks to the result
    result.append(2d_block) 

Recursive alternative

A more advanced solution

def convert_list(a, b):
    if isinstance(a, list):
        # Recursive call on all sub list
        return [convert_list(a[i], b[i]) for i in range(len(a))]
    else
        # When we find an element, return a if b is not 0
        return a if b!=0 else 0

This is a recursive function so you don't need to mind about the dimensions of your blockquote (as look as a and b have the same lengh)

Using numpy

Inspired by msamsami anwser, with a step to convert all non-zero numbers in b to 1 to avoid multiplying the result (zeros stay 0 so we can filter a values)

# Convert b to an array with 0 and 1, to avoid multiplying by 2 
def toBinary(item):
    if isinstance(item, list):
        return [toBinary(x) for x in item]
    else:
        return item != 0

filter = toBinary(b)

result = np.array(a) * np.array(filter)
  • Related