排序dicts列表时如何使用operator.itemgetter忽略None值?

iva*_*lan 5 python sorting python-2.7 python-3.x

我需要按特定值对字典列表进行排序。不幸的是,有些值是 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)
Run Code Online (Sandbox Code Playgroud)

我在 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'
Run Code Online (Sandbox Code Playgroud)

我需要什么(这适用于 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}]
Run Code Online (Sandbox Code Playgroud)

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

python中小于负无穷大的数字?

一切都大于无吗?

使用算术运算符将 None 与内置类型进行比较?

当不涉及字典时,我可以在 Python 3 中重新创建 Python 2 的排序行为。但是我看不到与操作员一起执行此操作的方法。

bin*_*con 8

对于 Python 3:正如这里提到的你可以在你的情况下做这样的事情:

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}]
Run Code Online (Sandbox Code Playgroud)


Nic*_* M. 5

我找到了一种通过在值上使用 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
Run Code Online (Sandbox Code Playgroud)

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

我希望它有帮助,

  • `return -float('inf') if nb is None else nb` 将是表达 `weighted()` 的更短的方式。:-) (3认同)