【问题标题】:multiple keys in nested dictionary嵌套字典中的多个键
【发布时间】:2018-10-29 09:04:43
【问题描述】:

代码

from operator import itemgetter
names = {
    'Bucky': 'Roberts',
    'Tom': 'Roberts',
    'Bernie' : 'Zunks',
    'Jenna' : 'Hayes',
    'Sally': 'Jones',
    'Amanda':'Roberts',
    'Tom':'Williams',
    'Dean':'Hayes',
    'Bernie':'Barbie',
    'Tom':'Jones'
    }
users = []
for k,v in names.items():
    users.append({'fname':k,'lname':v})
print(users)
for x in sorted(users, key=itemgetter('fname')):
    print(x)

问题:对于最后一个for 循环(排序一个)来显示字典names 的所有条目,我还需要所有条目,即重复键(一对多映射) .但是在创建嵌套字典users 时,会遗漏 2 个Tom(s) 和 1 个Bernie。使用python 3.4如何避免?

【问题讨论】:

  • 问题出在你定义names时。
  • dict 中不能有重复的键,因此在创建 names 字典时,TomBernie 键会被后面的条目覆盖。如果您想保留重复的条目,请将条目作为元组存储在 list(或 set,如果您不关心顺序)中。
  • @Rex5,更好的是有一个具有多个值的键,即你可以有一个键(常见的 fname)指向一个列表对应的lname例如 {'Bernie': ['Zunks', 'Barbie']}。您可以在我的回答中查看完整示例。

标签: python dictionary nested python-3.4


【解决方案1】:

一些可能的改进,但对于您的主要问题,使用全名和 set 作为您的结构,并在空间上使用 split 创建另一个字典(我不确定您是否需要):

names = {
    'Bucky Roberts',
    'Tom Roberts',
    'Bernie Zunks',
    'Jenna Hayes',
    'Sally Jones',
    'Amanda Roberts',
    'Tom Williams',
    'Dean Hayes',
    'Bernie Barbie',
    'Tom Jones'
}

users = []
for name in names:
    k, v = name.split()
    users.append({'fname':k,'lname':v})
for x in sorted(users, key=itemgetter('fname')):
    print(x)

生产:

{'fname': 'Amanda', 'lname': 'Roberts'}
{'fname': 'Bernie', 'lname': 'Barbie'}
{'fname': 'Bernie', 'lname': 'Zunks'}
{'fname': 'Bucky', 'lname': 'Roberts'}
{'fname': 'Dean', 'lname': 'Hayes'}
{'fname': 'Jenna', 'lname': 'Hayes'}
{'fname': 'Sally', 'lname': 'Jones'}
{'fname': 'Tom', 'lname': 'Williams'}
{'fname': 'Tom', 'lname': 'Jones'}
{'fname': 'Tom', 'lname': 'Roberts'}

编辑:使用元组并添加Betty Sue Johnson

names = {
    ('Bucky', 'Roberts'),
    ('Betty Sue', 'Johnson'),
    ('Tom', 'Roberts'),
    ('Bernie', 'Zunks'),
    ('Jenna', 'Hayes'),
    ('Sally', 'Jones'),
    ('Amanda', 'Roberts'),
    ('Tom', 'Williams'),
    ('Dean', 'Hayes'),
    ('Bernie', 'Barbie'),
    ('Tom', 'Jones')
}

for each in sorted([{'fname':n[0], 'lname':n[1]} for n in names], key=itemgetter('fname')):
    print(each)

有输出:

{'fname': 'Amanda', 'lname': 'Roberts'}
{'fname': 'Bernie', 'lname': 'Zunks'}
{'fname': 'Bernie', 'lname': 'Barbie'}
{'fname': 'Betty Sue', 'lname': 'Johnson'}
{'fname': 'Bucky', 'lname': 'Roberts'}
{'fname': 'Dean', 'lname': 'Hayes'}
{'fname': 'Jenna', 'lname': 'Hayes'}
{'fname': 'Sally', 'lname': 'Jones'}
{'fname': 'Tom', 'lname': 'Roberts'}
{'fname': 'Tom', 'lname': 'Williams'}
{'fname': 'Tom', 'lname': 'Jones'}

【讨论】:

  • 贝蒂苏约翰逊会讨厌这个。最好将名字和姓氏放在元组中。
  • 这确实服务于目的,尤其是。 split() 步骤。我会尝试按照@zwer 的建议将条目作为元组存储在列表中。泰。
  • @tdelaney 添加了一个包含元组和更少代码的示例(以及可怜的 ole Betty Sue)
【解决方案2】:

dict 不能有重复的键,您可能需要考虑其他数据结构,例如元组列表。

from operator import itemgetter

names = [
    ('Bucky', 'Roberts'),
    ('Tom', 'Roberts'),
    ('Bernie', 'Zunks'),
    ('Jenna', 'Hayes'),
    ('Sally', 'Jones'),
    ('Amanda','Roberts'),
    ('Tom', 'Williams'),
    ('Dean', 'Hayes'),
    ('Bernie', 'Barbie'),
    ('Tom', 'Jones')
    ]

users = [{'fname': k,'lname': v} for k, v in names]

【讨论】:

    【解决方案3】:

    字典不能有重复的键,因此需要将原始数据更改为其他内容......例如包含名字和姓氏的全名字符串列表,以空格分隔。

    在 Python 3.6 之前,字典中的项目是无序的,因此您可以将结果存储在 collections.OrderedDict 子类中,以保留插入键的顺序(如果您希望保留它)(这将在 Python 中继续工作) 3.6 以及更早的版本)。

    把所有东西放在一起,会产生这样的结果:

    from collections import OrderedDict
    from operator import itemgetter
    from pprint import pprint
    
    names = ['Bucky Roberts',
             'Tom Roberts',
             'Bernie Zunks',
             'Jenna Hayes',
             'Amanda Roberts',
             'Tom Williams',
             'Dean Hayes',
             'Bernie Barbie',
             'Tom Jones',]
    
    users = OrderedDict()
    for name in sorted(names):
        fname, lname = name.split()
        users.setdefault(fname, []).append(lname)
    
    pprint(users)
    

    输出:

    OrderedDict([('Amanda', ['Roberts']),
                 ('Bernie', ['Zunks', 'Barbie']),
                 ('Bucky', ['Roberts']),
                 ('Dean', ['Hayes']),
                 ('Jenna', ['Hayes']),
                 ('Tom', ['Roberts', 'Williams', 'Jones'])])
    

    【讨论】:

      【解决方案4】:

      您也可以使用defaultdict

      考虑以下

      from collections import defaultdict
      
      names = defaultdict(list)
      
      names['Bucky'].append('Roberts')
      
      names['Tom'].append('Roberts')
      
      names['Bernie'].append('Zunks')
      
      names['Jenna'].append('Hayes')
      
      names['Sally'].append('Jones')
      
      names['Amanda'].append('Roberts')
      
      names['Tom'].append('Williams')
      
      names['Dean'].append('Hayes')
      
      names['Bernie'].append('Barbie')
      
      names['Tom'].append('Jones')
      print names
      

      输出:

      defaultdict(list,
                  {'Amanda': ['Roberts'],
                   'Bernie': ['Zunks', 'Barbie'],
                   'Bucky': ['Roberts'],
                   'Dean': ['Hayes'],
                   'Jenna': ['Hayes'],
                   'Sally': ['Jones'],
                   'Tom': ['Roberts', 'Williams', 'Jones']})
      

      解释

      names = defaultdict(list) 初始化一个创建空列表的字典,而不是在查询不存在的键时抛出 KeyError

      因此,您可以像在字典中一样附加新键。

      制作用户列表如下

      users = []
      
      for fname in names:
          for lname in names[fname]:
              users.append({'fname': fname, 'lname': lname})
      

      【讨论】:

        【解决方案5】:

        @Rex5,字典被定义为具有唯一键的项目的无序集合。

        应该是不可变的数据项,但可以是可变的/不可变的。

        因此,定义本身在创建 names 字典时会过滤掉重复的值,因此不可能在 for 循环中包含重复的副本。

        看看下面的示例。在此之后我还修改了您的代码示例。

        专注于 SamKim 键。

        import json
        
        # Creating list of users (Dictionary) with duplicated keys
        users = {
        "Sam": "Smith",
        "Samuel": "Badri",
        "Kim": "Jones",
        "Jim": "Hollowen",
        "Sam": "Paul",
        "Joel": "Brown",
        "Kim": "Fillo",
        "Sam": "Koelli",
        "Tinnu": "Timmon"
        }
        
        # Pretty printing the dictionary
        # Keys, Sam & Kim will appear only once even after their multiple occurrences
        print( json.dumps(users, indent=4))
        
        # {
        #    "Kim": "Fillo",
        #    "Sam": "Koelli",
        #    "Tinnu": "Timmon",
        #    "Jim": "Hollowen",
        #    "Joel": "Brown",
        #    "Samuel": "Badri"
        # }
        

        我还尝试提供满足以下需求的替代答案(我所做的是我只是修改了字典和 for 循环)。

        from operator import itemgetter
        names = {
            'Bucky': 'Roberts',
            'Tom': ['Roberts', 'Williams', 'Jones'],
            'Bernie' : ['Zunks', 'Barbie'],
            'Jenna' : 'Hayes',
            'Sally': 'Jones',
            'Amanda':'Roberts',
            'Dean':'Hayes',
        }
        
        users = []
        for k,v in names.items():
            if type(v) == type([]):
                for lname in v:
                    users.append({'fname': k, 'lname': lname})
            else:
                users.append({'fname':k, 'lname':v})
        
        print(users)
        
        """
        [{'lame': 'Zunks', 'fname': 'Bernie'}, {'lname': 'Barbie', 
        'fname': 'Bernie'}, {'lname': 'Jones', 'fname': 'Sally'}, 
        {'lname': 'Hayes', 'fname': 'Jenna'}, {'lname': 'Roberts', 
        'fname': 'Amanda'}, {'lname': 'Roberts', 'fname': 'Bucky'}, 
        {'lname': 'Hayes', 'fname': 'Dean'}, {'lname': 'Roberts', 
        'fname': 'Tom'}, {'lname': 'Williams', 'fname': 'Tom'}, 
        {'lname': 'Jones', 'fname': 'Tom'}]
        """
        
        for x in sorted(users, key=itemgetter('fname')):
            print(x)
        
        """
        {'lname': 'Roberts', 'fname': 'Amanda'}
        {'lname': 'Zunks', 'fname': 'Bernie'}
        {'lname': 'Barbie', 'fname': 'Bernie'}
        {'lname': 'Roberts', 'fname': 'Bucky'}
        {'lname': 'Hayes', 'fname': 'Dean'}
        {'lname': 'Hayes', 'fname': 'Jenna'}
        {'lname': 'Jones', 'fname': 'Sally'}
        {'lname': 'Roberts', 'fname': 'Tom'}
        {'lname': 'Williams', 'fname': 'Tom'}
        {'lname': 'Jones', 'fname': 'Tom'}
        """
        

        【讨论】:

        • 我最好坚持使用默认字典。
        猜你喜欢
        • 2018-01-29
        • 1970-01-01
        • 2014-01-19
        • 1970-01-01
        • 2014-03-30
        • 1970-01-01
        • 2021-05-10
        • 2018-10-21
        • 2021-01-31
        相关资源
        最近更新 更多