【问题标题】:How to ignore None values with operator.itemgetter when sorting a list of dicts?在对字典列表进行排序时,如何使用 operator.itemgetter 忽略 None 值?
【发布时间】:2018-01-26 00:19:29
【问题描述】:

我需要按特定值对字典列表进行排序。不幸的是,有些值是 None 并且排序在 Python 3 中不起作用,因为它不支持 None 与非 None 值的比较。我还需要保留 None 值并将它们作为最低值放在新的排序列表中。

代码:

import operator

list_of_dicts_with_nones = [
    {"value": 1, "other_value": 4},
    {"value": 2, "other_value": 3},
    {"value": 3, "other_value": 2},
    {"value": 4, "other_value": 1},
    {"value": None, "other_value": 42},
    {"value": None, "other_value": 9001}
]

# sort by first value but put the None values at the end
new_sorted_list = sorted(
    (some_dict for some_dict in list_of_dicts_with_nones),
    key=operator.itemgetter("value"), reverse=True
)

print(new_sorted_list)

我在 Python 3.6.1 中得到了什么:

Traceback (most recent call last):
  File "/home/bilan/PycharmProjects/py3_tests/py_3_sorting.py", line 15, in <module>
    key=operator.itemgetter("value"), reverse=True
TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'

我需要什么(这适用于 Python 2.7):

[{'value': 4, 'other_value': 1}, {'value': 3, 'other_value': 2}, {'value': 2, 'other_value': 3}, {'value': 1, 'other_value': 4}, {'value': None, 'other_value': 42}, {'value': None, 'other_value': 10001}]

是的,我知道有与这个类似的问题,但他们不使用 operator.itemgetter 处理这个特殊用例:

A number smaller than negative infinity in python?

Is everything greater than None?

Comparing None with built-in types using arithmetic operators?

当不涉及字典时,我可以在 Python 3 中重新创建 Python 2 的排序行为。但我没有看到用运营商做到这一点的方法。

【问题讨论】:

    标签: python python-2.7 python-3.x sorting


    【解决方案1】:

    对于 Python 3:如 here 所述,您可以在您的情况下执行以下操作:

    L = [  # I mixed them to shown the sorting
         {"value": 1, "other_value": 4},
         {"value": 2, "other_value": 3},
         {"value": None, "other_value": 2},
         {"value": 4, "other_value": 1},
         {"value": None, "other_value": 42},
         {"value": 3, "other_value": 9001}
        ]
    
    L.sort(key= lambda x: (x['value'] is not None, x['value']), reverse=True)
    
    print(L)
    >>>[{'value': 4, 'other_value': 1}, {'value': 3, 'other_value': 9001}, {'value': 2, 'other_value': 3}, {'value': 1, 'other_value': 4}, {'value': None, 'other_value': 2}, {'value': None, 'other_value': 42}]
    

    【讨论】:

      【解决方案2】:

      我找到了一种方法,方法是在值上使用 lambda 键。这是代码:

      L = [  # I mixed them to shown the sorting
          {"value": 1, "other_value": 4},
          {"value": 2, "other_value": 3},
          {"value": None, "other_value": 2},
          {"value": 4, "other_value": 1},
          {"value": None, "other_value": 42},
          {"value": 3, "other_value": 9001}
      ]
      
      def weighted(nb):
          if nb is None:
              return -float('inf')
          else:
              return nb
      
      L.sort(key=lambda x:weighted(x["value"]), reverse=True)
      print(L) # => return the expected output in python 3.6
      

      可能还有另一种方法可以更短地编写“加权”函数,但它确实有效。这个想法只是为 None 值返回 -infinite 然后按值排序。

      希望对你有帮助

      【讨论】:

      • return -float('inf') if nb is None else nb 是表达weighted() 的更短的方式。 :-)
      【解决方案3】:

      我会先过滤掉None 的值,然后按照通常的方式进行排序:

      my_list = [d for d in my_list if all(d.values())]
      

      【讨论】:

        【解决方案4】:

        maxsize 是 Python 数据结构的最大大小,例如一个列表中可以有多少个元素。 从技术上讲,这不是可能的最小整数(因为 Python 3 具有无限整数值),但在正常用例中应该足够了。

        import operator 
        import sys
        
        my_list = [
            {"value": 1, "other_value": 4},
            {"value": 2, "other_value": 3},
            {"value": 3, "other_value": 2},
            {"value": 4, "other_value": 1},
            {"value": None, "other_value": 42},
            {"value": None, "other_value": 9001}
        ]
        
        def key(e):
            v = e["value"]
            return -sys.maxsize if v is None else v
        
        new_sorted_list = sorted((my_list ),
            key=key, reverse=True
        )
        
        print(new_sorted_list)
        

        给予,

        [{'value': 4, 'other_value': 1}, {'value': 3, 'other_value': 2}, {'value': 2, 'other_value': 3}, {'value': 1, 'other_value': 4}, {'value': None, 'other_value': 42}, {'value': None, 'other_value': 9001}]
        
        [Program finished]
        

        【讨论】:

          猜你喜欢
          • 2011-06-09
          • 2010-09-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多