Element-wise product of two 2-D lists

前端 未结 4 1728
[愿得一人]
[愿得一人] 2021-01-21 05:06

I can\'t use Numpy or any other library function as this is a question I have to do, I have to define my own way.

I am writing a function that takes two lists (2 dimensi

相关标签:
4条回答
  • 2021-01-21 05:39

    You could use numpy arrays. They are your best option as they run on a C background and hence are much faster computationally

    First, install numpy. Shoot up your terminal (CMD if you're in windows), type

    pip install numpy
    

    or, if in Linux, sudo pip install numpy

    Then, go on to write your code

    import numpy as np
    
    list1=np.array([[2,3,5,6,7],[5,2,9,3,7]]) #2 dimensional list example
    list2=np.array([[5,2,9,3,7],[1,3,5,2,2]])
    
    prod = np.multiply(list1,list2)
    # or simply, as suggested by Mad Physicist,
    prod = list1*list2
    
    0 讨论(0)
  • 2021-01-21 05:43

    Here is a function that can handle any type of iterable, nested to any level (any number of dimensions, not just 2):

    def elementwiseProd(iterA, iterB):
        def multiply(a, b):
            try:
                iter(a)
            except TypeError:
                # You have a number
                return a * b
            return elementwiseProd(a, b)
        return [multiply(*pair) for pair in zip(iterA, iterB)]
    

    This function works recursively. For each element in a list, it checks if the element is iterable. If it is, the output element is a list containing the elementwise multiplication of the iterables. If not, the product of the numbers is returned.

    This solution will work on mixed nested types. A couple of assumptions that are made here are that all the levels of nesting are the same size, and that an element that is a number in one iterable (vs a nested iterable), is always a number in the other.

    In fact, this snippet can be extended to apply any n-ary function to any n iterables:

    def elementwiseApply(op, *iters):
        def apply(op, *items):
            try:
                iter(items[0])
            except TypeError:
                return op(*items)
            return elementwiseApply(op, *items)
        return [apply(op, *items) for items in zip(*iters)]
    

    To do multiplication, you would use operator.mul:

    from operator import mul
    list1=[[2,3,5,6,7], [5,2,9,3,7]] 
    list2=[[5,2,9,3,7], [1,3,5,2,2]]
    elementwiseApply(mul, list1, list2)
    

    produces

    [[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
    
    0 讨论(0)
  • 2021-01-21 05:52

    In Python, it's generally better to loop directly over the items in a list, rather than looping indirectly using indices. It makes the code easier to read as well as more efficient since it avoids the tedious index arithmetic.

    Here's how to solve your problem using traditional for loops. We use the built-in zip function to iterate over two (or more) lists simultaneously.

    def elementwise_product(list1,list2):
        result = []
        for seq1, seq2 in zip(list1,list2):
            prods = []
            for u, v in zip(seq1, seq2):
                prods.append(u * v)
            result.append(prods)
        return result
    
    list1=[[2,3,5,6,7], [5,2,9,3,7]] 
    list2=[[5,2,9,3,7], [1,3,5,2,2]]
    
    print(elementwise_product(list1,list2))
    

    output

    [[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
    

    We can use list comprehensions to make that code a lot more compact. It may seem harder to read at first, but you'll get used to list comprehensions with practice.

    def elementwise_product(list1,list2):
        return [[u*v for u, v in zip(seq1, seq2)] 
            for seq1, seq2 in zip(list1,list2)]
    
    0 讨论(0)
  • 2021-01-21 05:55

    You can zip the two lists in a list comprehension, then further zip the resulting sublists and then finally multiply the items:

    list2 = [[5,2,9,3,7],[1,3,5,2,2]]
    list1 = [[2,3,5,6,7],[5,2,9,3,7]]
    
    result = [[a*b for a, b in zip(i, j)] for i, j in zip(list1, list2)]
    print(result)
    # [[10, 6, 45, 18, 49], [5, 6, 45, 6, 14]]
    

    Should in case the lists/sublists do not have the same number of elements, itertools.izip_longest can be used to generate fill values such as an empty sublist for the smaller list, or 0 for the shorter sublist:

    from itertools import izip_longest
    
    list1 = [[2,3,5,6]]
    list2 = [[5,2,9,3,7],[1,3,5,2,2]]
    result = [[a*b for a, b in izip_longest(i, j, fillvalue=0)] 
                   for i, j in izip_longest(list1, list2, fillvalue=[])]
    print(result)
    # [[10, 6, 45, 18, 0], [0, 0, 0, 0, 0]]
    

    You may change the inner fillvalue from 0 to 1 to return the elements in the longer sublists as is, instead of a homogeneous 0.


    Reference:

    List comprehensions

    0 讨论(0)
提交回复
热议问题