【问题标题】:create a dict with first name as key, full name associated with the key as value创建一个字典,名字作为键,与键关联的全名作为值
【发布时间】:2018-12-21 16:59:14
【问题描述】:

我有一个清单:

name_list = ["David Joyner", "David Zuber", "Brenton Joyner",
             "Brenton Zuber", "Nicol Barthel", "Shelba Barthel",
             "Shelba Crowley", "Shelba Fernald", "Shelba Odle",
             "Shelba Fry", "Maren Fry"]

我想写一个函数来返回一个字典,其中名字作为键,与名字相关的所有全名作为值:

 {'Shelba': ['Shelba Barthel', 'Shelba Crowley', 'Shelba Fernald', 
 'Shelba Odle', 'Shelba Fry'], 'David': ['David Joyner', 'David Zuber'], 
 'Brenton': ['Brenton Joyner', 'Brenton Zuber'], 'Maren': ['Maren Fry'], 
 'Nicol': ['Nicol Barthel']}

谢谢。

【问题讨论】:

  • 你尝试过什么,到底有什么问题?
  • 使用一个 collection.defaultdict(list) 并浏览你的列表一次
  • all_name = {n: [n2 if n2.startswith(n) for n2 in name_list] for n in [n3.split() for n3 in name_list]} 我不相信我的第一个列表理解是正确的,if 语句。
  • @PrestonHager 不太 - 请参阅我的回答中的“坏”解决方案。列表组合不适用于这种操作,因为您多次遍历整个列表 - (正确)使用的 defaultdict(list) 仅遍历列表一次

标签: python python-3.x dictionary


【解决方案1】:

聪明的方式(通过你的名单):

from collections import defaultdict

name_list = ["David Joyner", "David Zuber", "Brenton Joyner",
             "Brenton Zuber", "Nicol Barthel", "Shelba Barthel",
             "Shelba Crowley", "Shelba Fernald", "Shelba Odle",
             "Shelba Fry", "Maren Fry"]

rv = defaultdict(list)
for elem in name_list:
    rv[elem.split()[0]].append(elem) 

print(dict(rv))

输出:

{'David':  ['David Joyner', 'David Zuber'], 
 'Brenton':['Brenton Joyner', 'Brenton Zuber'], 
 'Nicol':  ['Nicol Barthel'], 
 'Shelba': ['Shelba Barthel','Shelba Crowley','Shelba Fernald','Shelba Odle','Shelba Fry'], 
 'Maren':  ['Maren Fry']}

缓慢的方式(可能看起来不错,但效率低下):

d = {key:[n for n in name_list if n.startswith(key)] 
          for key in set( p.split()[0] for p in name_list)}

这在计算上比defaultdict 版本差得多,因为它多次遍历列表:

  • 一次 创建set( p.split()[0] for p in name_list)
  • 对于我们刚刚收集的每个名称,它都会再次遍历完整列表以创建 dict-value [n for n in name_list if n.startswith(key)]

如果您之后需要排序,只需在您的 dicts 值上使用 list.sort()

# sorting the data afterwards
for k in rv:
    rv[k].sort(key = lambda x:x.split()[1]) # to sort by last names

输出:

# only difference when sorted: see key `Shelba`
{'David':  ['David Joyner', 'David Zuber'], 
 'Brenton':['Brenton Joyner', 'Brenton Zuber'], 
 'Nicol':  ['Nicol Barthel'], 
 'Shelba': ['Shelba Barthel','Shelba Crowley','Shelba Fernald','Shelba Fry','Shelba Odle'], 
 'Maren':  ['Maren Fry']}

【讨论】:

    【解决方案2】:

    正如 Patrick Artner 在 cmets 中建议的那样,使用 defaultdict。这个怎么样:

    from collections import defaultdict
    
    name_list = ["David Joyner", "David Zuber", "Brenton Joyner",
                 "Brenton Zuber", "Nicol Barthel", "Shelba Barthel",
                 "Shelba Crowley", "Shelba Fernald", "Shelba Odle",
                 "Shelba Fry", "Maren Fry"]
    
    name_dict = defaultdict(list)
    
    for first_name in set([name.split()[0] for name in name_list]):
        name_dict[first_name] = [name for name in name_list if name.split()[0] == first_name]
    
    print(name_dict)
    #defaultdict(<class 'list'>, {'Maren': ['Maren Fry'], 'David': ['David Joyner', 'David Zuber'], 'Nicol': ['Nicol Barthel'], 'Shelba': ['Shelba Barthel', 'Shelba Crowley', 'Shelba Fernald', 'Shelba Odle', 'Shelba Fry'], 'Brenton': ['Brenton Joyner', 'Brenton Zuber']})
    

    【讨论】:

    • 在创建值并预先创建集合时,您会通过多次迭代列表来抵消 defaultdict 的优势
    【解决方案3】:

    试试这个:

    def build_dict(name_list)
    result_dict = {}
    for name in name_list:
        names = name.split(" ")
        if names[0] in result_dict:
            result_dict[names[0]].append(names[1])
        else:
            result_dict[names[0]] = [names[1]]
    
    return result_dict
    

    想法是迭代名称列表,将每个名称拆分为名字和姓氏,查看名字是否在字典中。如果是,请查找并将姓氏附加到姓氏列表中。如果不是,则为其分配一个唯一成员是姓氏的列表

    【讨论】:

      【解决方案4】:
      def name_lists(name_list):
          d = {}
          
          for name in name_list:
                      
              first_name = name.split()[0]
              if first_name in d:
                  
                  d[first_name].append(name)
                  d[first_name].sort()
                  
              else:
                  d[first_name]=[name]
      
          return d
      

      【讨论】:

      • 答案在技术上是正确的,但效率很低,因为您在每次插入列表后进行排序。也没有指定应该对输出顺序进行排序。相反,它似乎只是遵循输入顺序。您还可以使用setdefault 字典方法使代码更简单、更优雅。
      【解决方案5】:
      def name_counts(name_list):
          result_dict = {}
          for name in name_list:
              names = name.split(" ")
              if names[0] in result_dict:
                  result_dict[names[0]] += 1
              else:
                  result_dict[names[0]] = 1
          return result_dict 
      

      【讨论】:

      • 在回答代码时请务必添加说明,它可以帮助其他人理解所做的事情。
      【解决方案6】:
      def name_lists(n_list):
          result_dict = {}
          n_list.sort()
          for name in n_list:
              names = name.split(" ")
              if names[0] in result_dict:
                  result_dict[names[0]].append(name)
              else:
                  result_dict[names[0]] = [name]
          return result_dict
      

      【讨论】:

      • 请提供一些信息,说明您所针对的问题的哪一部分,以及您是如何解决的
      猜你喜欢
      • 2021-10-07
      • 2016-02-28
      • 1970-01-01
      • 2013-05-01
      • 2021-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-14
      相关资源
      最近更新 更多