Hammad Manzoor
Hammad Manzoor

Reputation: 154

Element-wise product of two 2-D lists

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)

Upvotes: 3

Views: 2263

Answers (4)

Moses Koledoye
Moses Koledoye

Reputation: 78554

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

Upvotes: 6

Mad Physicist
Mad Physicist

Reputation: 114420

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

Upvotes: 2

PM 2Ring
PM 2Ring

Reputation: 55489

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

Upvotes: 1

R. S. Nikhil Krishna
R. S. Nikhil Krishna

Reputation: 4240

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

Upvotes: -1

Related Questions