0

i have 2 lists

a=[[2,3,5],[3,6,2],[1,3,2]]
b=[4,2,1]

i want the output to be:

c=[[8,12,20],[6,12,4],[1,3,2]]

At present i am using the following code but its problem is that the computation time is very high as the number of values in my list are very large.The first list of list has 1000 list in which each list has 10000 values and the second list has 1000 values.Therefore the computation time is a problem.I want a new idea in which computation time is less.The present code is:

a=[[2,3,5],[3,6,2],[1,3,2]]
b=[4,2,1]
c=[]
s=0
for i in b:
    c1=[]
    t=0
    s=s+1
    for j in a:
        t=t+1
        for k in j:
            if t==s:
                m=i*k
                c1.append(m)
    c.append(c1)
print(c)
Mazdak
  • 105,000
  • 18
  • 159
  • 188
Shubham Sharda
  • 653
  • 1
  • 6
  • 5

3 Answers3

4

You can use numpy :

>>> import numpy as np
>>> a=np.array([[2,3,5],[3,6,2],[1,3,2]])
>>> b=np.array([4,2,1])

>>> a*np.vstack(b)
array([[ 8, 12, 20],
       [ 6, 12,  4],
       [ 1,  3,  2]])

Or as @csunday95 suggested as a more optimized way you can use transpose instead of vstack :

>>> (a.T*b).T 
array([[ 8, 12, 20],
       [ 6, 12,  4],
       [ 1,  3,  2]])
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • For sure use numpy if you have to use python for something so computationally expensive. – csunday95 Jul 23 '15 at 20:31
  • it takes about 5-6 sec now to compute,earlier it took nearly 10 mins. Thanks a lot – Shubham Sharda Jul 23 '15 at 20:33
  • IF you wanna make your code extra fancy you can do (a.T*b).T as well – csunday95 Jul 23 '15 at 20:35
  • @Kasramvd just did a timeit of both, (a.T*b).T took an average of .045 seconds for a 100 by 100 array times a 100 length array, while method in answer took .63849 seconds – csunday95 Jul 23 '15 at 20:42
  • I suspected something was amiss when `numpy` was slower than a simple comprehension for manipulating such a large data structure. I don't know what the change does (never used `numpy`), but that's a huge performance increase. Good stuff! – TigerhawkT3 Jul 23 '15 at 20:55
  • @TigerhawkT3 I think the vstack is still faster than native python, but I'm pretty sure it's much slower to change dims in numpy than to transpose, as transpose doesn't do any copying it just changes the traversal rules. – csunday95 Jul 23 '15 at 21:09
  • 1
    @csunday95 Yes you are right changing the dims doesn't improve the performance, but as TigerhawkT3 said list comprehension performs better here, and i think the reason is that list comprehensions performs in C like numpy but the transpose in numpy and the opration * which actually applies some loops makes it take longer time to execute! – Mazdak Jul 23 '15 at 21:22
  • Any way I asked a question about this problem http://stackoverflow.com/questions/31598677/why-list-comprehension-is-very-faster-than-numpy-for-multiplying-the-arrays – Mazdak Jul 23 '15 at 21:50
4

Use zip() to combine each list:

a=[[2,3,5],[3,6,2],[1,3,2]]
b=[4,2,1]

[[m*n for n in second] for m, second in zip(b,a)]
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
  • it is fastest of all the so far mentioned.you have saved me a lot of time.computation time reduced from 10 min to 3-4 sec.thanks a lot. – Shubham Sharda Jul 23 '15 at 20:31
-1

This may not be faster, but it's a neater way of doing it :)

c = []
b_len = len(b)
for i in range(len(a)):
    b_multiplier = b[i%b_len]
    c.append([x*b_multiplier for x in a[i]])

Alternate short way now I've actually read the question properly and realised a and b are the same length:

c = [[x*b[i] for x in a[i]] for i in range(len(a))]  
Peter
  • 3,186
  • 3
  • 26
  • 59
  • When possible, I would recommend avoiding the use of `range(len(...` as well as hard-coded "magic numbers" (the `3` in there). Fortunately, `i%3` is unnecessary and you can replace it with just `i`. You'd also need to initialize `c` somewhere before appending to it. – TigerhawkT3 Jul 23 '15 at 20:28
  • Well, I was assuming the first 3 lines would still be there, but what's wrong with `range(len())` and the 'hard-coded magic numbers'? I'm just curious because I've not heard that before, also I'm doing it in python 2.7 so for me just `i` wouldn't work :) – Peter Jul 23 '15 at 20:42
  • `range(len(...` is generally an artifact of more traditional languages that didn't have an easy way of iterating over a sequence's items and therefore needed to do something like `for (int n=0; n++; n<10) {...` and use that `n` as an index. Python doesn't have that issue. – TigerhawkT3 Jul 23 '15 at 20:51
  • "Magic numbers" are specific values that may or may not need to change later, but don't have an easy way of being changed. For example, the `3` in your code, or including the actual number of sales tax rate in the formula for a tax calculator instead of having the formula access a variable. Hard-coding a value makes for code that is generally more difficult to maintain. – TigerhawkT3 Jul 23 '15 at 20:52
  • When `i` is guaranteed to be less than `3`, `i%3` has no additional effect. There's literally no need to do it. Your version of Python has no impact on this. – TigerhawkT3 Jul 23 '15 at 20:53
  • Yeah thanks, I kinda forgot that `b` may not be 3 values all the time. As to the range bit, I only use it if I need to access the index value, most of the time I try avoid it if possible :) Without the `%` it'll come up with index errors unless I'm mistaken, I was making it so that `a` can be any length, not just 3 values – Peter Jul 23 '15 at 20:55
  • Since `a` and `b` have the same length, and you're using a `range`, you can just use the element in that `range`. For these particular `a` and `b`, `i` would start with a value of `0`, then `1` on the next loop, then `2` on the final loop. You can just use `i`. – TigerhawkT3 Jul 23 '15 at 20:59
  • I may be misunderstanding you here haha, but wouldn't that not work if `a` has more than 3 loops, or if `b` is a different number of values that don't match `a`? ;p – Peter Jul 23 '15 at 21:02
  • Why would the number of loops being more than 3 have anything to do with it? You're getting the number of loops from the length of `a`. If `a` and `b` had different lengths, the question would be substantively different (not a matrix multiplication). Just try running it without the modulus operation (i.e., `b_multiplier = b[i]`) instead of continuing to insist that it wouldn't work. I think you'll be surprised. :) – TigerhawkT3 Jul 23 '15 at 21:06
  • Oh, I just re-read the question and realised the number of numbers in `b` matches the number of lists in `a`, I'd been testing assuming `a` had a lot more records than `b`, but I get your point now ;P – Peter Jul 23 '15 at 21:11