Element-wise product of two 2-D lists

时间:2016-10-20 13:13:15

标签: python list python-2.7

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 dimensional) as arguments. The function should calculate the element-wise product of both lists and store them in a third list and return this resultant list from the function. An example of the input lists are:

list1:

[[2,3,5,6,7],[5,2,9,3,7]]  

list2:

[[5,2,9,3,7],[1,3,5,2,2]]

The function prints the following list:

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

That is 2*5=10, 3*2=6, 5*9=45 ... and so on.

This is my code below, but it is only for a list with 2 lists (elements) inside in it like the example above and works perfectly fine for that, but what I want is to edit my code so that no matter how many number of lists (elements) are there in the 2-D list, it should print out its element-wise product in a new 2-D list e.g. it should also work for

[[5,2,9,3,7],[1,3,5,2,2],[1,3,5,2,2]]

or

[[5,2,9,3,7],[1,3,5,2,2],[1,3,5,2,2],[5,2,9,3,7]]

or any number of lists there are within the whole list.

def ElementwiseProduct(l,l2):
    i=0
    newlist=[] #create empty list to put prouct of elements in later
    newlist2=[]
    newlist3=[] #empty list to put both new lists which will have proudcts in them
    while i==0:
        a=0
        while a<len(l[i]):
            prod=l[i][a]*l2[i][a] #corresponding product of lists elements
            newlist.append(prod) #adding the products to new list
            a+=1
        i+=1
    while i==1:
        a=0
        while a<len(l[i]):
            prod=l[i][a]*l2[i][a] #corresponding product of lists elements
            newlist2.append(prod) #adding the products to new list
            a+=1
        i+=1
    newlist3.append(newlist)
    newlist3.append(newlist2)
    print newlist3

#2 dimensional list example
list1=[[2,3,5,6,7],[5,2,9,3,7]] 
list2=[[5,2,9,3,7],[1,3,5,2,2]]  
ElementwiseProduct(list1,list2)

4 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:2)

这是一个可以处理任何类型的iterable的函数,嵌套到任何级别(任意数量的维度,而不仅仅是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)]

此函数递归工作。对于列表中的每个元素,它检查元素是否可迭代。如果是,则输出元素是包含迭代的元素乘法的列表。如果没有,则返回数字的乘积。

此解决方案适用于混合嵌套类型。这里做出的一些假设是,所有嵌套级别都是相同的大小,并且一个可迭代的数字元素(相对于嵌套的可迭代)在另一个中始终是一个数字。

事实上,这个代码片段可以扩展为将任何n元函数应用于任何n个迭代:

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)]

要进行乘法运算,您可以使用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)

产生

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

答案 2 :(得分:1)

在Python中,通常最好直接循环遍历列表中的项目,而不是使用索引间接循环。它使代码更容易阅读,也更有效,因为它避免了繁琐的索引算法。

以下是使用传统for循环解决问题的方法。我们使用内置的zip函数同时迭代两个(或更多)列表。

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))

<强>输出

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

我们可以使用list comprehensions使代码更紧凑。一开始看起来似乎比较难读,但你会习惯用练习来列出理解。

def elementwise_product(list1,list2):
    return [[u*v for u, v in zip(seq1, seq2)] 
        for seq1, seq2 in zip(list1,list2)]

答案 3 :(得分:-1)

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