1

I have a multi dimensional list:

multiDimList = [['a',1],['a',1],['a',1],['b',2],['c',3],['c',3]]

I'm trying to sum the instances of element [1] where element [0] is common.

To put it more clearly, my desired output is another multi dimensional list:

multiDimListSum = [['a',3],['b',2],['c',6]]

I see I can access, say the value '2' in multiDimList by

x = multiDimList [3][1]

so I can grab the individual elements, and could probably build some sort of function to do this job, but it'd would be disgusting.

Does anyone have a suggestion of how to do this pythonically?

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
Ben Mayo
  • 1,285
  • 2
  • 20
  • 37
  • What do you mean by disgusting, Any approach to a problem is justified if gets the desirable output. – ZdaR Mar 19 '15 at 11:06
  • You are right of course. It's just I tend to write code that stinks, and as a inexperienced coder I'm pretty self deprecating. I always try to provide examples of what I've tried on SO, but in this instance I think I'd just be way off base. – Ben Mayo Mar 19 '15 at 11:11

3 Answers3

3

Assuming your actual sequence has similar elements grouped together as in your example (all instances of 'a', 'b' etc. together), you can use itertools.groupby() and operator.itemgetter():

from itertools import groupby
from operator import itemgetter

[[k, sum(v[1] for v in g)] for k, g in groupby(multiDimList, itemgetter(0))]

# result: [['a', 3], ['b', 2], ['c', 6]]
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • As you anticipated, I hadn't included all the nuances of the problem in my example. To first sort my list, I combined your answer with: http://stackoverflow.com/questions/20099669/python-sort-multidimensional-array-based-on-2nd-element-of-subarray – Ben Mayo Mar 19 '15 at 11:54
1

Zero Piraeus's answer covers the case when field entries are grouped in order. If they're not, then the following is short and reasonably efficient.

from collections import Counter
reduce(lambda c,x: c.update({x[0]: x[1]}) or c, multiDimList, Counter())

This returns a collection, accessible by element name. If you prefer it as a list you can call the .items() method on it, but note that the order of the labels in the output may be different from the order in the input even in the cases where the input was consistently ordered.

Uri Granta
  • 1,814
  • 14
  • 25
  • 1
    It's probably worth mentioning that `reduce()` is no longer a builtin in Python 3.x, and has to be imported from `functools`. But yes, this is a good solution where the input isn't grouped. – Zero Piraeus Mar 19 '15 at 12:00
0

You could use a dict to accumulate the total associated to each string

d = {}
multiDimList = [['a',1],['a',1],['a',1],['b',2],['c',3],['c',3]]
for string, value in multiDimList:
    # Retrieves the current value in the dict if it exists or 0
    current_value = d.get(string, 0) 
    d[string] += value
print d # {'a': 3, 'b': 2, 'c': 6}

You can then access the value for b by using d["b"].

El Bert
  • 2,958
  • 1
  • 28
  • 36