【问题标题】:Sort dictionary of lists by key value pairs按键值对对列表字典进行排序
【发布时间】:2019-12-30 15:33:14
【问题描述】:

我正在尝试对列表字典中的值进行排序,并从中创建一个新列表。这是数据:

{
    'fbi': [229, 421, 586, 654, 947, 955, 1095, 1294, 1467, 2423, 3063, 3478, 3617, 3730, 3848, 3959, 4018, 4136, 4297, 4435, 4635, 4679, 4738, 5116, 5211, 5330, 5698, 6107, 6792, 6906, 7036], 
    'comey': [605, 756, 1388, 1439, 1593, 1810, 1959, 2123, 2506, 3037, 6848], 
    'hillary': [14, 181, 449, 614, 704, 1079, 1250, 2484, 2534, 2659, 3233, 3374, 3488, 3565, 4076, 4756, 4865, 6125, 7109]
}

我正在尝试在其中找到 20 个最小值并获取它们对应的键的列表。例如,前三个最小值是 14(希拉里)、181(希拉里)和 229(联邦调查局)。因此,我怎样才能得到这样的列表:

['hillary', 'hillary', 'fbi']

所有值总是不同的。此外,列表中的所有值都按升序到降序排序。

这是我尝试过的:

for m in range(1,20):
    for i in sort_vals.values():
        if i[0] < a[0]:
            a[0] = i[0]

这给了我最小的价值,但不是任何其他的,因为在一次迭代之后,最小的价值总是相同的。我想如果我可以删除那个特定的值,那会很有帮助。想不出别的了。谢谢!

【问题讨论】:

    标签: python python-3.x list dictionary


    【解决方案1】:

    您可以将字典(此处为d)展平为具有相应key/value 对的元组列表,并根据值对元组进行排序:

    from operator import itemgetter
    
    l = [(k,i) for k,v in d.items() for i in v]
    # [('fbi', 229), ('fbi', 421), ('fbi', 586), ('fbi', 654),...
    list(zip(*sorted(l, key=itemgetter(1))[:3]))[0]
    # ('hillary', 'hillary', 'fbi')
    

    【讨论】:

      【解决方案2】:

      你可以

      1. 反转映射,创建带有数字的字典 => 名称列表
      2. 将此字典排序(作为元组)
      3. 选择前 3 个项目

      像这样:

      import collections
      
      d = collections.defaultdict(list)
      data = {'fbi': [229, 421, 586, 654, 947, 955, 1095, 1294, 1467, 2423, 3063, 3478, 3617, 3730, 3848, 3959, 4018, 4136, 4297, 4435, 4635, 4679, 4738, 5116, 5211, 5330, 5698, 6107, 6792, 6906, 7036], 'comey': [605, 756, 1388, 1439, 1593, 1810, 1959, 2123, 2506, 3037, 6848], 'hillary': [14, 181, 449, 614, 704, 1079, 1250, 2484, 2534, 2659, 3233, 3374, 3488, 3565, 4076, 4756, 4865, 6125, 7109]}
      
      for k,vlist in data.items():
          for v in vlist:
              d[v].append(k)
      
      result = [v[0] for k,v in sorted(d.items())[:3]]
      
      print(result)
      

      打印出来:

      ['hillary', 'hillary', 'fbi']
      

      请注意,如果有多个名称附加到一个值,此代码将只选择第一个 (v[0])

      【讨论】:

      • 希望一个数字只在一个列表中
      • 在这种情况下它会起作用。但我想概述另一种情况。
      【解决方案3】:

      只需在 sorted() 中使用 lambda 函数即可。

      l = [(k,i) for k,v in d.items() for i in v]
      res = [v[0] for v in sorted(l, key=lambda x: x[1])][:20]
      

      【讨论】:

        【解决方案4】:

        由于列表中的所有值都已排序,因此可以使用heapq.merge

        d = {
            'fbi': [229, 421, 586, 654, 947, 955, 1095, 1294, 1467, 2423, 3063, 3478, 3617, 3730, 3848, 3959, 4018, 4136, 4297, 4435, 4635, 4679, 4738, 5116, 5211, 5330, 5698, 6107, 6792, 6906, 7036], 
            'comey': [605, 756, 1388, 1439, 1593, 1810, 1959, 2123, 2506, 3037, 6848], 
            'hillary': [14, 181, 449, 614, 704, 1079, 1250, 2484, 2534, 2659, 3233, 3374, 3488, 3565, 4076, 4756, 4865, 6125, 7109]
        }
        import heapq
        pairs = [[(k, i) for i in v] for k, v in d.items()]
        sorted_pairs = heapq.merge(*pairs, key=lambda a: a[1])
        smallest_num_you_want = 3
        res = [next(sorted_pairs)[0] for i in range(smallest_num_you_want)]
        

        【讨论】:

          猜你喜欢
          • 2014-02-11
          • 1970-01-01
          • 2011-01-16
          • 1970-01-01
          • 2011-02-22
          • 2010-11-15
          • 2011-07-08
          • 1970-01-01
          相关资源
          最近更新 更多