处理列表中的冗余

问题描述 投票:0回答:5

假设我有一个包含州和县的元组列表:

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'}]
python-3.x list dictionary tuples
5个回答
7
投票

你会得到错误的结果,因为

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']}

3
投票

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
进行排序。


2
投票

我认为 zip() 不适合这个。这里有两个可能的解决方案。 如果您必须使用列表来存储结果,您将不得不在这个答案之后更进一步。但是,如果使用字典来获取结果可以,那么这个答案可能会帮助您实现目标:

 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': '李县'}, {'NC': '阿拉曼斯县'}]

新字典:{'VA':['弗雷德里克县'],'NJ':['伯灵顿县','米德尔塞克斯县'],'NC':['李县','阿拉曼斯县'],'MD ': ['蒙哥马利县']}


2
投票

列表理解似乎是最简单的方法

[{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'}]

1
投票

您的代码损坏的原因可能是由于对

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]) ] )
© www.soinside.com 2019 - 2024. All rights reserved.