【问题标题】:Creating inside keys in a dictionary using a for loop使用 for 循环在字典中创建内部键
【发布时间】:2019-11-23 13:57:18
【问题描述】:

我正在使用 for 循环从表中创建字典。目标是使用 for 循环创建具有嵌套键值对的字典。

表格为文本格式,第一行是表头,如下所示:

AAA|BBB|CCC
zzz|100|xy
zzz|50|xy
xxx|200|xy
xxx|100|xy
zzz|300|xz
zzz|400|xz
xxx|200|xz
xxx|700|xz

要按 AAA 获取总数,(在 AAA:CCC 键值对中),代码成功:

dict = {}

with open('data.txt') as table:
    table.readline()
    for line in table:
        (AAA, BBB, CCC) = line.split("|")
        dict[AAA] = dict[AAA] + int(BBB) if AAA in dict else int(BBB)

输出如预期:

{'zzz': 850, 'xxx': 1200}

下一步(也是我卡住的地方)是如何执行迭代以创建内部键,格式为

{'zzz':{xy:150, xz:700}, 'xxx':{xy:300, xz:900}}

这是我目前所拥有的,但不明白如何将 insideKey 插入到这个字典中:

dict = {}
new_dict = {}

with open('data.txt') as table:
    table.readline()
    for line in table:
        (AAA, BBB, CCC) = line.split("|")
        dict[AAA] = dict[AAA] + (new_dict[CCC] + int(BBB)) if CCC in new_dict else int(BBB)


我了解我无法使用 + 添加 insideKey,但找不到执行此操作的方法。

预期输出:

{'zzz':{xy:150, xz:700}, 'xxx':{xy:300, xz:900}}

【问题讨论】:

  • 你想对重复值做什么:xxx|200|xy xxx|100|xy {xxx:{ xy:?}} 应该是什么?
  • Mark Meyer:看起来 N N 想对它们求和。
  • 马克,应该加在一起,{xxx:{xy:300}}。把它想象成 xxx 是一个苹果,200 是数量,xy 是 Kevin,购买那个数量的人。在下一个实例中,xxx - 苹果,数量 100,也由 Kevin (xy) 购买。 xz 将是另一个人,Mike 说。因此,我们的字典键和值将是{apple:{Kevin:300, Mike:900}}

标签: python loops dictionary nested key


【解决方案1】:

您可以使用setdefault() 设置初始值。循环时只需设置适当的默认值或使用get 获取内部值或零:

d = {}
with open('data.txt') as table:
    next(table)
    for line in table:
        (AAA, BBB, CCC) = map(str.strip, line.split("|"))
        outer = d.setdefault(AAA, {})
        outer[CCC] = outer.get(CCC, 0) + int(BBB)

结果:

{'zzz': {'xy': 150, 'xz': 700}, 'xxx': {'xy': 300, 'xz': 900}}

【讨论】:

    【解决方案2】:

    一个快速的建议:不要使用 'dict' 作为字典 instance 的名称,因为它也是字典 class 的名称。 Python 允许您将绑定修改为内置名称。这很强大,但是如果你在那之后需要使用 dict() 构造函数,你将无法做到。

    现在,谈谈你的问题。我认为您试图在太少的代码行中完成太多工作。编写多行明确的行来代替该字典分配并不可耻。我还建议您通过构建更简单的字典作为中间步骤来重新组织问题。

    字典键可以是任何可以散列的不可变数据类型。这包括仅包含不可变数据的元组。该程序以您想要的方式为您提供汇总的数据,但并没有完全按照您想要的方式组织:

    dct = {}
    with open('data.txt') as table:
        table.readline()
        for line in table:
            (AAA, BBB, CCC) = line.split("|")
            v = int(BBB)     # value
            k = (AAA, CCC)   # key
            try:
                dct[k] += v  # existing key
            except KeyError:
                dct[k] = v   # new key
    

    此时,dct包含:

    {('zzz', 'xy'): 150, ('xxx', 'xy'): 300, ('zzz', 'xz'): 700, ('xxx', 'xz'): 900}
    

    现在,使用第二个循环创建一个新字典,按照您想要的方式重新组织。

    result = {}
    for (k1, k2), v in dct.items():
        try:
            result[k1][k2] = v
        except KeyError:
            result[k1] = {k2 : v}
    

    这是结果中的内容:

    {'zzz': {'xy': 150, 'xz': 700}, 'xxx': {'xy': 300, 'xz': 900}}
    

    我使用了 Python 初学者可能不知道的三个技巧:比字符串或数字更复杂的字典键;异常处理;和元组拆包。如果您还没有学习这些概念,您可能会发现它们非常有用。

    注意:如果您可以使用第三方包,Pandas DataFrames 是完成此类工作的绝佳工具。不过,如果您有大量数据处理工作要做,Pandas 可能才值得付出努力。

    【讨论】:

      【解决方案3】:

      只是为了说明使用 defaultdict。

      from collections import defaultdict
      
      d = defaultdict(dict)
      
      with open('f0714.txt', 'r') as table:
          next(table)
          for line in table:
              (AAA, BBB, CCC) = map(str.strip, line.split("|"))
      
              if CCC not in d[AAA]:
                  d[AAA][CCC] = int(BBB)
              else:
                  d[AAA][CCC] += int(BBB)
      
      print(dict(d))
      
      '''
      {'zzz': {'xy': 150, 'xz': 700}, 'xxx': {'xy': 300, 'xz': 900}}
      '''
      

      【讨论】:

      • 此时全力以赴:d = defaultdict(lambda: defaultdict(lambda: 0)) 完全跳过if,然后print({k: dict(v) for k, v in dict(d).items()}) 删除内部默认字典。
      猜你喜欢
      • 2018-11-03
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 2019-03-29
      • 1970-01-01
      • 2018-04-18
      相关资源
      最近更新 更多