5

Is there a more sensible way of doing this? I want to make a new list by summing over the indices of a lot of other lists. I'm fairly new to programming and this seems like a very clunky method!

list1 = [1,2,3,4,5]
list2 = [1,1,1,4,1]
list3 = [1,22,3,1,5]
list4 = [1,2,5,4,5]
...
list100 = [4,5,6,7,8]

i = 0
while i < len(list1):
    mynewlist[i] = list1[i]+list2[i]+list3[i]+list4[i]+...list100[i]
    i = i+1
FakeDIY
  • 1,425
  • 2
  • 14
  • 23

4 Answers4

17

This is a pretty good use case for zip.

>>> list1 = [1,2,3,4,5]
>>> list2 = [1,1,1,4,1]
>>> list3 = [1,22,3,1,5]
>>> list4 = [1,2,5,4,5]
>>> [sum(x) for x in zip(list1, list2, list3, list4)]
[4, 27, 12, 13, 16]

or if you have your data as a list of lists instead of separate lists:

>>> data = [[1,2,3,4,5], [1,1,1,4,1], [1,22,3,1,5], [1,2,5,4,5]]
>>> [sum(x) for x in zip(*data)]
[4, 27, 12, 13, 16]

similarly, if you store your data as a dict of lists, you can use dict.itervalues() or dict.values() to retrieve the list values and use that in a similar fashion:

>>> data = {"a":[1,2,3], "b":[3,4,4]}
>>> [sum(x) for x in zip(*data.itervalues())]
[4, 6, 7]

Note that if your lists are of unequal length, zip will work up till the shortest list length. For example:

>>> data = [[1,2,3,4,5], [1,1], [1,22], [1,2,5]]
>>> [sum(x) for x in zip(*data)]
[4, 27]

If you wish to get a result that includes all data, you can use itertools.izip_longest (with an appropriate fillvalue). Example:

>>> data = [[1,2,3,4,5], [1,1], [1,22], [1,2,5]]
>>> [sum(x) for x in izip_longest(*data, fillvalue=0)]
[4, 27, 8, 4, 5]
Shawn Chin
  • 84,080
  • 19
  • 162
  • 191
  • Thanks. I hadn't thought of doing it like this. However, thinking about it some more I think what I need is a dictionary, not a list of lists---I need each list member to be easily user accessible. I'll try and work out how to do what I want as a dictionary. – FakeDIY May 24 '12 at 10:37
  • @FakeDIY if you're using a `dict`, you can get the list of lists using [`.itervalues()`](http://docs.python.org/library/stdtypes.html#dict.itervalues) or [`.values()`](http://docs.python.org/library/stdtypes.html#dict.values), e.g. `[sum(x) for x in zip(*dct.itervalues())]` – Shawn Chin May 24 '12 at 11:36
6

While @Shawn's answer is correct, this is a case where I think map might be more elegant than list comprehensions:

>>> list1 = [1,2,3,4,5]
>>> list2 = [1,1,1,4,1]
>>> list3 = [1,22,3,1,5]
>>> list4 = [1,2,5,4,5]
>>> map(sum, zip(list1, list2, list3, list4))
[4, 27, 12, 13, 16]
Nolen Royalty
  • 18,415
  • 4
  • 40
  • 50
1

The problem in the first place is this: you should never have 100 variables in your code.

list1 = [1,2,3,4,5]
list2 = [1,1,1,4,1]
list3 = [1,22,3,1,5]
list4 = [1,2,5,4,5]
...
list100 = [4,5,6,7,8]

Instead, you should have something like

list_of_lists = []
list_of_lists.append([1,2,3,4,5])
list_of_lists.append([1,1,1,4,1])
list_of_lists.append([1,22,3,1,5])
list_of_lists.append([1,2,5,4,5])
...

Then you'd calculate the desired result like this:

[sum(x) for x in zip(*list_of_lists)]
bpgergo
  • 15,669
  • 5
  • 44
  • 68
  • 1
    However, if your lists aren't all the same length, zip will slice them to the smallest list's length (ignoring the tails). So, since zip essentially turns this set into a matrix, if your set is large enough, you may be better off using a numpy matrix. – Nisan.H May 23 '12 at 17:13
  • Yeah, it seemed that all lists are the same size, but it is important to emphasize that the code relies on this assumption, thanks. – bpgergo May 24 '12 at 08:18
  • The problem is that I also need to be able to access each list individually and in a user friendly manner. I think I need a dictionary, not a list of lists. – FakeDIY May 24 '12 at 10:35
0

You really need to read a python tutorial.

  1. sum(list1) will give you the sum of that list.
  2. You need to learn about for loops
  3. Your lists should themselves be stored in a list
  4. The way to rotate a collection of lists is to use zip:

    list1 = [1,2,3,4,5]
    list2 = [1,1,1,4,1]
    list3 = [1,22,3,1,5]
    zip(list1,list2,list3)
    # matches up element n of each list with element n of the other lists
    #=> [(1, 1, 1), (2, 1, 22), (3, 1, 3), (4, 4, 1), (5, 1, 5)]
    # now you want to add up each of those tuples:
    [sum(t) for t in zip(list1,list2,list3)]
    #=> [3, 25, 7, 9, 11]
    

To work a list of lists like this with zip, look at the itertools module, or learn about the *args syntax.

Marcin
  • 48,559
  • 18
  • 128
  • 201