16

If I have this type of dictionary:

a_dictionary = {"dog": [["white", 3, 5], ["black", 6,7], ["Brown", 23,1]],
                "cat": [["gray", 5, 6], ["brown", 4,9]],
                "bird": [["blue", 3,5], ["green", 1,2], ["yellow", 4,9]],
                "mouse": [["gray", 3,4]]
                }

And I would like to sum from first line 3 with 6 and 23 and on next line 5 with 4 on so on so I will have when printing:

dog [32, 13]
cat [9, 15]
bird [8, 16]
mouse [3,4]

I tried a for loop of range of a_dictionary to sum up by index, but then I can't access the values by keys like: a_dictionary[key]

But if I loop through a_dictionary like for key, value in a dictionary.items():, I can't access it by index to sum up the needed values.

I would love to see how this could be approached. Thanks.

medium-dimensional
  • 1,974
  • 10
  • 19
Erika
  • 211
  • 1
  • 7

7 Answers7

21

Generally, in Python you don't want to use indices to access values in lists or other iterables (of course this cannot be always applicable).

With clever use of zip() and map() you can sum appropriate values:

a_dictionary = {
    "dog": [["white", 3, 5], ["black", 6, 7], ["Brown", 23, 1]],
    "cat": [["gray", 5, 6], ["brown", 4, 9]],
    "bird": [["blue", 3, 5], ["green", 1, 2], ["yellow", 4, 9]],
    "mouse": [["gray", 3, 4]],
}

for k, v in a_dictionary.items():
    print(k, list(map(sum, zip(*(t for _, *t in v)))))

Prints:

dog [32, 13]
cat [9, 15]
bird [8, 16]
mouse [3, 4]

EDIT:

  1. With (t for _, *t in v) I'll extract the last two values from the lists (discarding the first string value)

    [3, 5], [6, 7], [23, 1]
    [5, 6], [4, 9]
    [3, 5], [1, 2], [4, 9]
    [3, 4]
    
  2. zip(*...) is a transposing operation

    (3, 6, 23), (5, 7, 1)
    (5, 4), (6, 9)
    (3, 1, 4), (5, 2, 9)
    (3,), (4,)
    
  3. Then I apply sum() on each of the sublist created in step 2. with map()

    32, 13
    9, 15
    8, 16
    3, 4
    
  4. The result of the map() is stored into a list

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • `Generally, in Python you don't want to use indices to access values in lists or other iterables` Why? (Honest question) – ihavenoidea Sep 11 '22 at 13:20
  • 2
    @ihavenoidea (1) The language isn't designed for it, so you'll find the libraries easier to use if you eschew indices. (2) It's easy to screw up (if you're currently pulling the second element out, will you remember to change all the "1"s when your data structure changes?). (3) It's harder to optimize into Python bytecode (which, yes, is a thing). – Jacob Manaker Sep 11 '22 at 16:01
  • @ihavenoidea Whereas e.g. C# distinguishes `for` from `foreach`, the former iterating typically with indices, Python uses one keyword for both, named `for` for brevity, but it actually behaves like `foreach`. And if you need both indices and values, you can use e.g. `for i, v in enumerate(x)`, or to take a more complicated example `for (i, v), (j, w) in product(enumerate(x), enumerate(y))`. (`enumerate` also has an optional argument for the index's starting value if you don't want it to be `0`.) – J.G. Sep 11 '22 at 20:58
  • I'm amazed about `for _, *t in v`, I did not know that was possible... If anyone else is interested, [this answer](https://stackoverflow.com/a/10532492/13997884) contains some good further information. – aasoo Sep 22 '22 at 12:50
6

You can create and sum temporary lists of an indexed element from each color using Python's list comprehension like:

for animal, colors in a_dictionary.items():
    print(
        animal,
        [
            sum([color[1] for color in colors]),
            sum([color[2] for color in colors]),
        ]
    )
Rob Croft
  • 124
  • 2
  • 1
    Simpler: `[sum(color[i] for color in colors) for i in [1, 2]]`. You don't need to create lists for `sum()`, and you don't need to repeat all the code inside `sum()` just to change the indices. – wjandrea Sep 11 '22 at 21:11
5
for key, value in my_dictionary.items():
    sum_1, sum_2 = 0, 0

    for sublist in value:
        sum_1 += sublist[1]
        sum_2 += sublist[2]

    print(key, [sum_1, sum_2])
omermikhailk
  • 116
  • 6
5

This one works for me:

results = {}
sum_x = 0
sum_y = 0
for key,value in a_dictionary.items():
    for i in range(len(value)):
        sum_x += value[i][1]
        sum_y += value[i][2]
    results[key] = [sum_x,sum_y]
    sum_x = 0
    sum_y = 0

Output:

results
{'dog': [32, 13], 'cat': [9, 15], 'bird': [8, 16], 'mouse': [3, 4]}
2
a_dictionary['dog']

[['white', 3, 5], ['black', 6, 7], ['Brown', 23, 1]]

a_dictionary['dog'][0]

['white', 3, 5]

a_dictionary['dog'][0][1]

3

Paul Wang
  • 1,666
  • 1
  • 12
  • 19
  • This is what I was going for on my own but I got index out of range every time. – Erika Sep 10 '22 at 22:18
  • 2
    make sure indexing start at 0 instead of 1. Python indexing started from 0. Is that the cause of you getting index out of range? – Paul Wang Sep 10 '22 at 22:30
1
for animal, values in a_dictionary.items():
sum_1 = 0
sum_2 = 0
    for lst in values:
        sum_1 += lst[1]
        sum_2 += lst[2]
    sum_list = [sum_1, sum_2]
    print(f'{animal} {sum_list}')
Deyan Romanov
  • 66
  • 1
  • 9
1

this works:

d = {}

for i, v in a_dictionary.items():
    s = 0
    for j in v:
        s = s + j[1]        
    d[i]=s
print(d)

returns this:

{'dog': 32, 'cat': 9, 'bird': 8, 'mouse': 3}
D.L
  • 4,339
  • 5
  • 22
  • 45