2

I have a nested dictionary

 dict_features =  {'agitacia/6.txt': {'samoprezentacia': 0, 'oskorblenie': 1},
                   'agitacia/21.txt': {'samoprezentacia': 0, 'oskorblenie': 0}}

I'm trying to output a new dictionary features_agit_sum which consists of a key from a previous dictionary and a sum of values of a "deeper" dictionary. So I need to sum 0+1 that is int type. The output should be:

{'agitacia/6.txt': 1, 'agitacia/21.txt': 0}

Below are several attempts with different errors; don't how to iterate correctly:

features_agit_sum = {}
def vector_agit_sum(dict_features):
    for key, value in dict_features:
        features_agit_sum[key] = sum(dict_features.items()[key])
        print (features_agit_sum)
    return features_agit_sum

ValueError: too many values to unpack (expected 2) dict_features.items()[key] - try to access deeper dict

features_agit_sum = {}
def vector_agit_sum(dict_features):
    for key in dict_features:
        for item, value in dict_features.items():
            features_agit_sum[key] = sum([item])
            print (features_agit_sum)
    return features_agit_sum

TypeError: unsupported operand type(s) for +: 'int' and 'str' - Why, it's integers!

features_agit_sum = {}
def vector_agit_sum(dict_features):
    files = dict_features.keys()
    for key, value in dict_features.items():
        features_agit_sum[files] = sum(dict_features.items()[key])
        print (features_agit_sum)
    return features_agit_sum

TypeError: 'dict_items' object is not subscriptable

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Vic Nicethemer
  • 1,081
  • 3
  • 16
  • 38

4 Answers4

3

Use a dict comprehension:

{key: sum(value.itervalues()) for key, value in dict_features.iteritems()}

If you are using Python 3, remove the iter prefixes, so use .values() and .items().

Demo:

>>> dict_features =  {'agitacia/6.txt': {'samoprezentacia': 0, 'oskorblenie': 1}, 'agitacia/21.txt': {'samoprezentacia': 0, 'oskorblenie': 0}}
>>> {key: sum(value.itervalues()) for key, value in dict_features.iteritems()}
{'agitacia/21.txt': 0, 'agitacia/6.txt': 1}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

Try this, using a dictionary comprehension (this will work in both Python 2.7+ and 3.x):

{ k : sum(v.values()) for k, v in dict_features.items() }

If using Python 2.7+, the recommended way is to explicitly use iterators, in Python 3.x the previous snippet already uses them:

{ k : sum(v.itervalues()) for k, v in dict_features.iteritems() }

Either way, it returns the expected result:

{'agitacia/21.txt': 0, 'agitacia/6.txt': 1}
Óscar López
  • 232,561
  • 37
  • 312
  • 386
0

Use isinstance to check the type and take the correct action. If it is a int, add it to the running total. Otherwise, recurse to get the total sum contained within that dictionary.

dict_features =  {'agitacia/6.txt': {'samoprezentacia': 0, 'oskorblenie': 1}, 'agitacia/21.txt': {'samoprezentacia': 0, 'oskorblenie': 0}}

def countDict(d):
    total = 0
    for i in d.itervalues():
        if isinstance(i,int):
            total += i
        else:
            total += countDict(i)
    return total



result = {}
for k,v in dict_features.iteritems():

    result[k] = countDict(v)

print result
Eric Urban
  • 3,671
  • 1
  • 18
  • 23
0

the shortest (and fastest) way may be as this:

features_agit_sum = dict([(k, sum(dict_features[k].values())) for k, v in dict_features.iteritems()])
fransua
  • 1,559
  • 13
  • 30