Объединить кортежи с одним и тем же ключом

Как объединить кортеж с тем же ключом

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)