【问题标题】:Handling for redundancy in a list处理列表中的冗余
【发布时间】:2019-02-19 09:39:35
【问题描述】:

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

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 zipper


【解决方案1】:

你会得到错误的结果,因为zip 将字符串视为可迭代对象。这是预期的行为。

你可能会得到接近你想要的东西:

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

print(result)

Result 是一个带有列表的字典。输出:

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

【讨论】:

  • 这个解决方案效果很好,并且产生了我正在寻找的确切结果。假设地说,如果我想在每个元组中添加第三项:[('NJ', 'Burlington County', '3/12/2018'), ('NJ', 'Middlesex County', '7/3/2011'), ('NJ', 'Burlington County', '8/13/2015')],那么最终结果将是{'NJ': [{'Burlington County': [ '3/12/2018', '8/13/2015']},{'Middlesex County':['7/3/2011']} ]},我将如何调整?
  • @gwydion93 在这个假设的情况下,您需要使用相同的技术再执行一步 - 只是使方法链更长。以for state, county, date in stList: 开始for 循环,循环套件为result.setdefault(state, dict()).setdefault(county, list()).append(date)。您将获得带有列表的字典。
【解决方案2】:

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

【讨论】:

  • 我问过@Poolka 这个问题,但是如果我想为每个元组添加一个额外的date 项目并创建[('NJ', 'Burlington County', '3/12/2018'), ('NJ', 'Middlesex County', '7/3/2011'), ('NJ', 'Burlington County', '8/13/2015')] 以便最终结果为{'NJ': [{'Burlington County': [ '3/12/2018', '8/13/2015']},{'Middlesex County':['7/3/2011']} ]},我该怎么做用你的方法做到这一点?看起来 ``defaultdict` 只处理 2 个项目 - 一个为 k,另一个为 v
  • @gwydion93 我在答案中添加了示例,使用 defaultdict 绝对有可能。
  • 好的,最后一条评论:当我运行上面的代码时,它给了我一个奇怪的输出:defaultdict(<function __main__.<lambda>()>, {'NJ': defaultdict(list, {'Burlington County': ['3/12/2018', '8/13/2015'], 'Middlesex County': ['7/3/2011']})}) 有没有办法将它转换为带有defaultdict(<function <lambda> at 0x000001F25F24DD08>, etc... 部分的常规字典?
  • @gwydion93 这只是它的repr(字符串表示)。出于所有意图和目的,它的行为类似于普通字典。实际上,就 OOP 而言,数据结构是 dict,因为 defaultdictdict 的子类。检查isinstance(result, dict)
【解决方案3】:

我认为 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': 'Burlington County'}, {'NJ': 'Middlesex County'}, {'VA': 'Frederick County'}, {'MD': 'Montgomery County'} , {'NC': '李县'}, {'NC': '阿拉芒斯县'}]

新 dict: {'VA': ['Frederick County'], 'NJ': ['Burlington County', 'Middlesex County'], 'NC': ['Lee County', 'Alamance County'], 'MD': ['蒙哥马利县']}

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      您的代码被破坏的原因可能是由于对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]) ] )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-26
        • 1970-01-01
        • 2021-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-20
        相关资源
        最近更新 更多