How do I multiply each element in a list with nested lists and get the sum?

Viewed 214

I have a project that goes like this:

data = [[0, 1], [1, 1], [1, 0], [0, 1]]
res = [4, 2]

The objective is to multiply res with each element in data and get the sum. For example:

sum_prod = [[4*(0) + 2*(1)], [4*(1) + 2*(1)], [4*(1) + 2*(0)], [4*(0) + 2*(1)]]
sum_prod = [2, 6, 4, 2] # expected output

The code I have looks like this:

def fitness_score(g, u):
    a = g
    b = u
    arr = a @ ab
    fitness_value = arr.T.tolist()
    return fitness_value

And here is how to call the function fitness_score

fitness_score (data, res)

This snippet of code that I have works if the data to be called are numpy arrays

The problem is, there are parts in my code which doesn’t accept numpy arrays.

Is there anyway to change the code I have that would readily take lists rather than numpy arrays? So that I could use it all throughout my code?

Any help would be appreciated! Thanks!

4 Answers

You can use np.multiply, which accepts an array_like as input (and hence lists too) followed by sum along the second axis:

data = [[0, 1], [1, 1], [1, 0], [0, 1]]
res = [4, 2]

np.multiply(data, res).sum(1).tolist()
# [2, 6, 4, 2]

Alternatively, and for a more general scenario, you have np.asarray, which only creates an array if the input isn't one already, otherwise it returns a view into the input array:

def fitness_score(g, u):
    a = np.asarray(g)
    b = np.asarray(u)
    return (a@b).tolist()

fitness_score(data, res)
# [2, 6, 4, 2]

You can use numpy arrays:

import numpy as np

data = [[0, 1], [1, 1], [1, 0], [0, 1]]
res = [4, 2]

def fitness_score(g, u):
    t = np.array(g)*np.array(u)
    return [sum(n) for n in t]

print(fitness_score(data, res))

Output:

[2, 6, 4, 2]

If you want a pure python solution, so you won't have to convert back and forth:

list(map(sum, (map(lambda x: ([a*b for a, b in zip(x, res)]), data))))
Out[1]: [2, 6, 4, 2]

What it does: for every pair of elements in your longer list, it multiplies every element from the corresponding element in the shorter list, and sums them up. The result in 1 element per element in the long list.

A purer (and even less readable) version of @Nicolas Gervais' answer. No lambda, no comprehension:

import operator as op
[*map(sum,zip(*map(map,map(op.attrgetter("__mul__"),res),zip(*data))))]
# [2, 6, 4, 2]

Not so much a recommendation. More of a brain teaser for people who enjoy that sort of thing.

Related