Объединить кортежи с одним и тем же ключом
Как объединить кортеж с тем же ключом
list_1 = [("AAA", [123]), ("AAA", [456]), ("AAW", [147]), ("AAW", [124])]
и превратить их в
list_2 = [("AAA", [123, 456]), ("AAW", [147, 124])]
Ответы
Ответ 1
Наиболее эффективный подход заключается в использовании словаря collections.defaultdict
для хранения данных в виде расширяющегося списка, а затем при необходимости конвертировать обратно в кортеж/список:
import collections
list_1 = [("AAA", [123]), ("AAA", [456]), ("AAW", [147]), ("AAW", [124])]
c = collections.defaultdict(list)
for a,b in list_1:
c[a].extend(b) # add to existing list or create a new one
list_2 = list(c.items())
результат:
[('AAW', [147, 124]), ('AAA', [123, 456])]
обратите внимание, что преобразованные данные, вероятно, лучше оставить в словаре. Преобразование в список снова теряет "ключевую" функцию словаря.
С другой стороны, если вы хотите сохранить порядок "ключей" исходного списка кортежей, если вы не используете python 3.6/3.7, вам придется создать список с оригинальными "ключами" (упорядоченный, уникальный), а затем перестроить список из словаря. Или используйте OrderedDict
но тогда вы не можете использовать defaultdict
(или использовать рецепт)
Ответ 2
Вы можете использовать dict для отслеживания индексов каждого ключа, чтобы сохранить временную сложность O (n):
list_1 = [("AAA", [123]), ("AAA", [456]), ("AAW", [147]), ("AAW", [124])]
list_2 = []
i = {}
for k, s in list_1:
if k not in i:
list_2.append((k, s))
i[k] = len(i)
else:
list_2[i[k]][1].extend(s)
list_2
станет:
[('AAA', [123, 456]), ('AAW', [147, 124])]
Ответ 3
Вы можете создать словарь и прокрутить список. Если элемент, присутствующий в словаре, добавляет значение в уже существующий список, еще назначьте значение ключу.
dict_1 = {}
for item in list_1:
if item[0] in dict_1:
dict_1[item[0]].append(item[1][0])
else:
dict_1[item[0]] = item[1]
list_2 = list(dict_1.items())
Ответ 4
Подобно другим ответам, вы можете использовать словарь для связывания каждого ключа со списком значений. Это реализовано в функции merge_by_keys
в фрагменте кода ниже.
import pprint
list_1 = [("AAA", [123]), ("AAA", [456]), ("AAW", [147]), ("AAW", [124])]
def merge_by_key(ts):
d = {}
for t in ts:
key = t[0]
values = t[1]
if key not in d:
d[key] = values[:]
else:
d[key].extend(values)
return d.items()
result = merge_by_key(list_1)
pprint.pprint(result)