2

I am asking this question to get a starting point of the Pythonic way to reduce some of the list contents in the following dictionary using list comprehensions:

{'cycle1': [1, 2407, 2393, 14],
 'cycle2': [2, 1657, 1652, 5], 
 'cycle3': [3, 2698, 2673, 25], 
 'cycle4': [4, 2116, 2102, 14], 
 'cycle5': [5, 2065, 2048, 17], 
 'cycle6': [6, 1633, 1615, 18]}

Each list's columns, though not marked, have these headers:

section_num,account_total,billable_count,nonbillable_count

I want to sum each of the last three columns, account_total, billable_count, non-billable_count in a list comprehension.

I'm just not sure how to sum going through each list member in a comprehension. I need to ask for the values of each key, each value being a list. I'm just a little unsure about how to do that.

m0nhawk
  • 22,980
  • 9
  • 45
  • 73
octopusgrabbus
  • 10,555
  • 15
  • 68
  • 131
  • The Pythonic way is to have the dict contents be objects rather than lists... – user9876 May 08 '13 at 18:05
  • Specific example? I basically thought I could represent cycle, and the remaining values as a list. What other method would I do? Python isn't forcing objects these days is it? – octopusgrabbus May 08 '13 at 18:06
  • If I understand correctly you have 4 separate related values - `section_num`, `account_total`, `billable_count`, `nonbillable_count`. In any programming language that looks like an object with 4 distinct fields, not a list. Obviously you _can_ use a list but you have to document it, remember which list index is which field, etc - that might work but it makes maintenance harder, so I think it's bad style unless you have a very good reason that's not mentioned in the question. – user9876 May 08 '13 at 18:12

2 Answers2

3

How about using zip? This does an individual sum of each column, although I'm not sure that is what you want.

[sum(x) for x in zip(*my_dict.values())[1:]]

This outputs:

[12576, 12483, 93]
squiguy
  • 32,370
  • 6
  • 56
  • 63
  • I'm a little confused. What does the '*' do in `*my_dict.values())`? Also, I'm getting this error in 2.7 [sum(x) for x in zip(*my_dict.values())[1:]] Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not callable – octopusgrabbus May 08 '13 at 18:04
  • It's a way to unpack all the arguments in your data structure. See this link: http://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists – squiguy May 08 '13 at 18:05
  • or see http://stackoverflow.com/questions/2921847/python-once-and-for-all-what-does-the-star-operator-mean-in-python for an explanation – Fredrik Pihl May 08 '13 at 18:06
  • @octopusgrabbus Odd, it works for me in 2.7.3. Did you mix a variable name up or not copy it correctly by accident? – squiguy May 08 '13 at 18:10
2

a bit unclear about the output-format requested, but the line below sums the second column:

In [13]: c = {'cycle1': [1, 2407, 2393, 14],
 'cycle2': [2, 1657, 1652, 5], 
 'cycle3': [3, 2698, 2673, 25], 
 'cycle4': [4, 2116, 2102, 14], 
 'cycle5': [5, 2065, 2048, 17], 
 'cycle6': [6, 1633, 1615, 18]}

In [14]: sum([v[1] for k, v in c.iteritems()])
Out[14]: 12576

Using python3.3

>>> sum([v[1] for v in c.values()])
12576
Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
  • I am basically looking to create a cycle -- let's call it cycle9 -- that ignores each list's 0th element and sums all element 1 values, all element 2 values, and all element 3 values. – octopusgrabbus May 08 '13 at 18:01
  • ah, then you need the solution given by @squiguy – Fredrik Pihl May 08 '13 at 18:02
  • Also got this error: sum([v[1] for k, v in c.iteritems()]) Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not callable – octopusgrabbus May 08 '13 at 18:08
  • see updated example, works for me (tm) using 2.7. SLight modification needed for 3.3 – Fredrik Pihl May 08 '13 at 18:12
  • Remove the `[]` square brackets inside `sum` to have a generator expression, which is more efficient, instead of a list comprehension. – jamylak May 10 '13 at 08:52