How to perform element-wise arithmetic operations (e.g. add, subtract, multiply) of two equally shaped lists with arbitrary nestings

别等时光非礼了梦想. 提交于 2021-02-08 08:35:17

问题


I want to perform element-wise mathematical operations (e.g. sum, multiply..) on two Python lists containing numbers or multiple nested lists which may contain again numbers or lists and so on.

The shapes of the two lists are equal when performing the operation. Furthermore, the result should be of the same shape as the two input lists.

A shape may differ in:

  1. length,

  2. width (i.e. number of nestings),

  3. order (e.g. the lists start with a number followed by a nested list, but it may also be that it starts with a nested list, followed by numbers).

The shape changes arbitrarily each time I want to perform a mathematical operation.

How can I perform math operations on arbitrarily shaped lists?

In the past, I've implemented a customized piece of code for each different shape, similar to 1, 2, 3, 4, 5, 6, 7, 8, 9, but I was wondering if there is already a more general solution in the form of a library or reference code for this.

Example 1 (summation):

a = [ 1, 2, 3, 4,[ 5, 6, 7, 8]]
b = [10,20,30,40,[50,60,70,80]]
c = elementwiseSUM(a,b)
c

would result in

[11, 22, 33, 44, [55, 66, 77, 88]]

Example 2 (summation):

d = [ 1,[ 2, 3],  4, [ 5, 6, 7], [[ 8], [ 9, 10]]]
e = [10,[20,30], 40, [50,60,70], [[80], [90,100]]]
f = elementwiseSUM(d,e)
f

would result in

[11, [22, 33], 44, [55, 66, 77], [[88], [99, 110]]]

Example 3 (multiplication):

g = [[4,2],1,1]
h = [[8,3],1,9]
i = elementwiseMUL(g,h)
i

would result in

[[32, 6], 1, 9]

elementwiseSUM() and elementwiseMUL() are placeholders for the library functions which I am looking for.


回答1:


Here's the solution I came up with

a = [ 1,  2,  3,  4, [ 5,  6,  7,  8]]
b = [10, 20, 30, 40, [50, 60, 70, 80]]

def element_wise(a, b, f):
    return [element_wise(i, j, f) if type(i) == list and type(j) == list else f(i, j) for i, j in zip(a, b)]

c = element_wise(a, b, lambda x, y: x + y) # [11, 22, 33, 44, [55, 66, 77, 88]]

so a and b are your lists, and f is the function you want to apply, as you can see I wrote a simple function to add ints

You can either write your own lambdas or just use the operator module.




回答2:


It's not exactly taking advantage of a built-in python module (besides operator), but how about something like this?

def element_wise(list_a, list_b, operator):
    result = []
    assert len(list_a) == len(list_b)
    for a, b in zip(list_a, list_b):
        is_lists = isinstance(a, list) and isinstance(b, list)
        is_ints = isinstance(a, int) and isinstance(b, int)

        if is_lists:
            result.append(element_wise(a, b, operator))
        elif is_ints:
            result.append(operator(a, b))
        else:
            raise ValueError
    return result


def main():

    from operator import add, mul

    list_sum_a = [ 1,  2,  3,  4, [ 5,  6,  7,  8]]
    list_sum_b = [10, 20, 30, 40, [50, 60, 70, 80]]

    list_mul_a = [[4, 2], 1, 1]
    list_mul_b = [[8, 3], 1, 9]

    result_sum = element_wise(list_sum_a, list_sum_b, add)
    result_mul = element_wise(list_mul_a, list_mul_b, mul)

    print(result_sum)
    print(result_mul)

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

Output:

[11, 22, 33, 44, [55, 66, 77, 88]]
[[32, 6], 1, 9]



回答3:


Unsure about any library that has a built in method, but using one wouldn't be any faster than creating one yourself

an example that is not any kind of production code but shows an easy way to do this is:

import operator
ops = {
    "+": operator.add,
    "-": operator.sub,
    "*": operator.mul,
    "/": operator.div
}

a = [ 1,[ 2, 3],  4, [ 5, 6, 7], [[ 8], [ 9, 10]]]
b = [10,[20,30], 40, [50,60,70], [[80], [90,100]]]


def foo(x, y, op):
    if type(x) == list:
        return [foo(a, b, op) for a, b in zip(x, y)]
    else:
        return ops[op](x, y)

#Run
print foo(a, b, '+')



回答4:


I am giving the solution code for example one and three, But this solution is totally depends on your list i.e. How many list you have inside the list because i am using for loop and that depends on your list.

Example 1 (summation solution)

a = [ 1, 2, 3, 4,[ 5, 6, 7, 8]]
b = [10,20,30,40,[50,60,70,80]]   
def elementwiseSUM(a, b):
    pl = []
    cl = []
    for i, j in zip(a, b):
        if type(i) and type(j) != list:
            pl.append(i+j)
        if type(i) and type(j) == list:
            for k, l in zip(i, j):
                cl.append(k+l)
    pl.append(cl)
    return pl
print(elementwiseSUM(a, b))

Example 2 (multiplication solution)

g = [[4,2],1,1]
h = [[8,3],1,9]
def elementwiseMUL(g, h):
    pl = []
    cl = []
    for i, j in zip(g, h):
        if type(i) and type(j) != list:
            cl.append(i*j)
        if type(i) and type(j) == list:
            for k, l in zip(i, j):
                pl.append(k*l)
    pl.append(cl)
    return pl
print(elementwiseMUL(g, h))


来源:https://stackoverflow.com/questions/57615420/how-to-perform-element-wise-arithmetic-operations-e-g-add-subtract-multiply

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!