Как заставить элемент из dict накапливать другие элементы в python - PullRequest
0 голосов
/ 25 марта 2020

У меня есть следующая структура python списков словарей (назовем это dict1):

dict1 = {"word1": {'111.txt': 1, '112.txt': 3, '113.txt': 2},
         "word2": {'111.txt': 2, '112.txt': 2, '113.txt': 1},
         "word3": {'111.txt': 1, '113.txt': 1},
         "word4": {'111.txt': 3, '113.txt': 2},
         "word5": {'111.txt': 5, '113.txt': 1}}

, и я хотел бы создать новый словарь (dict2), где у меня есть ключи dict1 и сумма элементов этого ключа в качестве его элементов. Таким образом:

{'111.txt': 12, '112.txt': 5, '113.txt': 7}

Я попытался сделать следующий код ниже, однако он хранит только последний элемент dict1 в dict2, то есть он не накапливает значения dict1

for i,j in dict1.items():
     for k,w in j.items():
            dict2[k] =+ j[k]

Вывод следующий: он оставляет только последний элемент dict1, сумма не накапливается.

{'111.txt': 5, '112.txt': 2, '113.txt': 1}

Кто-нибудь знает, что может быть неправым в коде? Или у тебя есть идея получше?

Ответы [ 3 ]

3 голосов
/ 25 марта 2020

Проблема, с которой вы здесь сталкиваетесь, заключается в том, что вам нужно использовать +=, а не =+. Просмотрите этот пример кода в python tutor , и вы увидите, что =+ рассматривается как назначение, а не добавление на месте. Здесь - это пример кода с += и небольшим дополнительным логином c, вы увидите его правильно.

2 голосов
/ 25 марта 2020

Я не уверен, как вы инициализируете dict2, поэтому трудно указать на проблему в вашем коде. Сказав это, ниже приведены некоторые способы решения этой проблемы.

Предполагая, что ваши данные в формате вложенного словаря {'word1': {'111.txt': 1, '112.txt': 3, '113.txt': 2}, 'word2':..}, я полагаю, что вы стремитесь к:

d = {
    'word1': {'111.txt': 1, '112.txt': 3, '113.txt': 2},
    'word2': {'111.txt': 2, '112.txt': 2, '113.txt': 1},
    'word3': {'111.txt': 1, '113.txt': 1},
    'word4': {'111.txt': 3, '113.txt': 2},
    'word5': {'111.txt': 5, '113.txt': 1}
}

counts = {}

# only need to iterate values here. 'word1', 'word2' etc. not needed in output
for v1 in d.values():

    # iterate sub dictionary values and keys. These are needed for output. 
    for k, v2 in v1.items():

        # Use dict.get() to set initial value to 0 if key doesn't exist
        counts[k] = v2 + counts.get(k, 0)

print(counts)
# {'111.txt': 12, '112.txt': 5, '113.txt': 7}

Или даже к простому подходу, подобному приведенному ниже:

counts = {}
for v1 in d.values():
    for k, v2 in v1.items():

        # initialize to 0 if key doesn't exist
        if k not in counts:
            counts[k] = 0

        # Continue counting, since above condition will prevent KeyError
        counts[k] += v2

print(counts)
# {'111.txt': 12, '112.txt': 5, '113.txt': 7}

Кроме того, вы также можете использовать collections.Counter здесь:

from collections import Counter

d = {
    'word1': {'111.txt': 1, '112.txt': 3, '113.txt': 2},
    'word2': {'111.txt': 2, '112.txt': 2, '113.txt': 1},
    'word3': {'111.txt': 1, '113.txt': 1},
    'word4': {'111.txt': 3, '113.txt': 2},
    'word5': {'111.txt': 5, '113.txt': 1}
}

counts = Counter()
for v in d.values():
    counts.update(v)

print(counts)
# Counter({'111.txt': 12, '113.txt': 7, '112.txt': 5})

Который использует Counter.update(), чтобы легко добавлять значения.

Здесь также можно использовать collections.defaultdict(int):

from collections import defaultdict

d = {
    'word1': {'111.txt': 1, '112.txt': 3, '113.txt': 2},
    'word2': {'111.txt': 2, '112.txt': 2, '113.txt': 1},
    'word3': {'111.txt': 1, '113.txt': 1},
    'word4': {'111.txt': 3, '113.txt': 2},
    'word5': {'111.txt': 5, '113.txt': 1}
}

counts = defaultdict(int)
for v1 in d.values():
    for k, v2 in v1.items():
        counts[k] += v2

print(counts)
# defaultdict(<class 'int'>, {'111.txt': 12, '112.txt': 5, '113.txt': 7})

Примечание: Counter и defaultdict являются подклассами dict, так что вы можете обращаться с ними как с обычными словарями. Если вы действительно хотите, чтобы результат был dict, вместо этого вы можете привести dict():

print(dict(counts))
# {'111.txt': 12, '112.txt': 5, '113.txt': 7}

Они также обрабатывают инициализацию для вас, поэтому вам не нужно инициализировать новые ключи с помощью 0.

2 голосов
/ 25 марта 2020

Я считаю, что ошибка в том, как вы инициализируете dict2, но не могу сказать много, так как вы не опубликовали эту часть. Это должно работать, хотя:

dict1 = {"word1": {'111.txt': 1, '112.txt': 3, '113.txt': 2},
         "word2": {'111.txt': 2, '112.txt': 2, '113.txt': 1},
         "word3": {'111.txt': 1, '113.txt': 1},
         "word4": {'111.txt': 3, '113.txt': 2},
         "word5": {'111.txt': 5, '113.txt': 1}}

dict2 = dict()

for i, j in dict1.items():
    for k, w in j.items():
        dict2[k] = dict2.get(k, 0) + j[k]

print(dict2)

вывод:

{'112.txt': 5, '113.txt': 7, '111.txt': 12}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...