Обработка избыточности в списке - PullRequest
0 голосов
/ 14 сентября 2018

Допустим, у меня есть список кортежей с указанием штатов и округов:

stList = [('NJ', 'Burlington County'),
 ('NJ', 'Middlesex County'),
 ('VA', 'Frederick County'),
 ('MD', 'Montgomery County'),
 ('NC', 'Lee County'),
 ('NC', 'Alamance County')]

Для каждого из этих элементов я хочу объединить штат с округом, например:

new_list = [{'NJ': 'Burlington County'},
{'NJ': 'Middlesex County'},
{'VA': 'Frederick County'},
{'MD': 'Montgomery County'},
{'NC': 'Lee County'},
{'NC': 'Alamance County'}]

Я пробовал что-то подобное, но это не работает правильно (он перебирает каждую букву и упаковывает их по отдельности):

new_list = []
for item in stList:
  d1 = dict(zip(item[0], item[1]))
  new_list.append(d1)

Возвращает:

 [{'N': 'B', 'J': 'u'},
 {'N': 'M', 'J': 'i'},
 {'V': 'F', 'A': 'r'},
 {'M': 'M', 'D': 'o'},
 {'N': 'L', 'C': 'e'},
 {'N': 'A', 'C': 'l'}]

Чтобы усложнить задачу, моей конечной целью является создание списка словарей для каждого состояния (ключа), в котором в качестве списка указаны графства (значения). Как я могу исправить сжатый словарь и затем поместить округа в список для каждого штата?

final_list = [{'NJ': ['Burlington County', 'Middlesex County']},
{'VA': 'Frederick County'},
{'MD': 'Montgomery County'},
{'NC': ['Lee County', 'Alamance County'}]

Ответы [ 5 ]

0 голосов
/ 14 сентября 2018

Решение Poolka setdefault является звуковым, производительным и читабельным, но его можно сделать еще более интуитивным с помощью defaultdict:

from collections import defaultdict

result = defaultdict(list)
for state, county in stList:
    result[state].append(county)

Если в вашем списке есть триплеты с датами, вы можетесделать вложенную версию:

result = defaultdict(lambda: defaultdict(list))
for state, county, date in stList:
    result[state][county].append(date)

Для однострочника без какого-либо из вышеупомянутых атрибутов вы можете использовать itertools.groupby;)

from itertools import groupby
{k: [x[1] for x in g] for k, g in groupby(sorted(stList), key=lambda x: x[0])}

# {'NC': ['Alamance County', 'Lee County'], 
#  'MD': ['Montgomery County'], 
#  'NJ': ['Burlington County', 'Middlesex County'], 
#  'VA': ['Frederick County']}

С алгоритмической точки зрения это хуже, чемон должен отсортировать начальные list.

0 голосов
/ 14 сентября 2018

понимание списка, кажется, самый простой способ здесь

[{i[0]:i[1]} for i in stList]

ВЫХОД

[{'NJ': 'Burlington County'},
{'NJ': 'Middlesex County'},
{'VA': 'Frederick County'},
{'MD': 'Montgomery County'},
{'NC': 'Lee County'},
{'NC': 'Alamance County'}]
0 голосов
/ 14 сентября 2018

Причина, по которой ваш код не работает, возможно, из-за неправильного понимания zip.Это в основном обработка каждого имени как отдельного итератора и перебора первых двух символов s[:1].Если вы хотите сопоставить штаты и округа в каждом штате, попробуйте следующее:

mapping = {}
for state, cty in stList:
    if (state in mapping):
        mapping[state].append(cty)
    else:
        mapping[state] = [cty]

Это самый простой способ сделать это, во всяком случае.Однако, если вы хотите использовать itertools, вы можете сделать groupby следующим образом:

mapping = dict( [ (k, [gg[1] for gg in g]) for k, g in groupby(stList, key = lambda x: x[0]) ] )
0 голосов
/ 14 сентября 2018

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

 stList = [('NJ', 'Burlington County'),
 ('NJ', 'Middlesex County'),
 ('VA', 'Frederick County'),
 ('MD', 'Montgomery County'),
 ('NC', 'Lee County'),
 ('NC', 'Alamance County')]


new_list = []
for item in stList:
    new_list.append({item[0]:item[1]})

print "new list: ", new_list


new_dict = {}
for item in stList:
    if item[0] in new_dict:
        new_dict[item[0]].append(item[1])
    else:
        new_dict[item[0]] = [item[1]]

print "new dict: ", new_dict

Эти решения дают следующее:

новый список: [{'NJ': 'Округ Берлингтон'}, {'NJ': 'Округ Мидлсекс'}, {'VA': 'Округ Фредерик'}, {'MD': 'Округ Монтгомери'} , {'NC': 'Lee County'}, {'NC': 'Alamance County'}]

новый диктант: {'VA': ['' Округ Фредерик '],' NJ ': [' Округ Берлингтон ',' Округ Мидлсекс '],' NC ': [' Округ Ли ',' Округ Аламанс '], 'MD': ['Округ Монтгомери']}

0 голосов
/ 14 сентября 2018

Вы получите неправильный результат, потому что zip обрабатывает строки как итерационные. Ожидаемое поведение.

Вы можете получить что-то близкое к тому, что вы хотите, например:

result = dict()
for state, county in stList:
    result.setdefault(state, list()).append(county)

print(result)

Результатом является один словарь со списками. Выход:

{'NJ': ['Burlington County', 'Middlesex County'], 'VA': ['Frederick County'], 'MD': ['Montgomery County'], 'NC': ['Lee County', 'Alamance County']}
...