排序列表,同时将 None 值推到最后

Posted

技术标签:

【中文标题】排序列表,同时将 None 值推到最后【英文标题】:Sort list while pushing None values to the end 【发布时间】:2013-08-27 00:29:24 【问题描述】:

我有一个具有 None 的同类对象列表,但它可以包含任何类型的值。 示例:

>>> l = [1, 3, 2, 5, 4, None, 7]
>>> sorted(l)
[None, 1, 2, 3, 4, 5, 7]
>>> sorted(l, reverse=True)
[7, 5, 4, 3, 2, 1, None]

有没有办法不用重新发明***来让列表按照通常的 python 方式排序,但在列表末尾有 None 值,就像这样:

[1, 2, 3, 4, 5, 7, None]

我觉得这里可以有一些“关键”参数的技巧

【问题讨论】:

值是否保证为ints 或None,还是需要None 才能对所有任意对象进行排序? 不,可以是字符串或无,浮点数和无。通常,它是具有 None 元素的同构列表 @NikolayGolub:为了将来参考,最好在问题中明确说明此类信息 - 毕竟,SethMMorton 的答案符合您的要求,但不符合您的实际要求,所以您不会如果 FJ 没有发生,就没有好的解决方案。 @abarnert 我的第一句话是“我有一个没有同构的对象列表”,所以我假设 OP 的列表不是异构的。 @abarnert 我明白你在说什么。我想这可以追溯到我们几天前的 XY 讨论。我现在明白为什么问“为什么?”很重要。 【参考方案1】:
>>> l = [1, 3, 2, 5, 4, None, 7]
>>> sorted(l, key=lambda x: (x is None, x))
[1, 2, 3, 4, 5, 7, None]

这将为列表中的每个元素构造一个元组,如果值为None,则为(True, None)的元组,如果值为其他任何值,则为(False, x)(其中x是值) .由于元组是逐项排序的,这意味着所有非None 元素将排在最前面(从False < True 开始),然后按值排序。

【讨论】:

我喜欢这个解决方案,因为它适用于所有类型的同类 litst 如果在此解决方案中使用reverse=True,请在键中使用x is not None,否则首先返回所有None值。 @tutuDajuju 如果要按值降序排序,则不需要具有 True 和 False 的元组,而 None 最后。如原始问题所示,您可以简单地为[7, 5, 4, 3, 2, 1, None] 执行sorted(l, reverse=True) @tutuDajuju 如果对日期时间之类的内容进行排序是正确的。 它确实处理列表中多个Nones 的情况。所有的 None 都被推到最后。【参考方案2】:

试试这个:

sorted(l, key=lambda x: float('inf') if x is None else x)

由于无穷大大于所有整数,None 将始终放在最后。

【讨论】:

哇!我不知道这个“inf”真棒! 如果列表包含无穷大或列表是字符串列表,则此方法不起作用。 @NeilG 是的,我们在问题本身的 cmets 中介绍了这一点。这个答案是针对最初发布的问题的,但仍然只适用于整数,所以我没有删除它。【参考方案3】:

我创建了一个函数,扩展了 Andrew Clark 的答案和 tutuDajuju 的评论。

def sort(myList, reverse = False, sortNone = False):
    """Sorts a list that may or may not contain None.
    Special thanks to Andrew Clark and tutuDajuju for how to sort None on https://***.com/questions/18411560/python-sort-list-with-none-at-the-end

    reverse (bool) - Determines if the list is sorted in ascending or descending order

    sortNone (bool) - Determines how None is sorted
        - If True: Will place None at the beginning of the list
        - If False: Will place None at the end of the list
        - If None: Will remove all instances of None from the list

    Example Input: sort([1, 3, 2, 5, 4, None, 7])
    Example Input: sort([1, 3, 2, 5, 4, None, 7], reverse = True)
    Example Input: sort([1, 3, 2, 5, 4, None, 7], reverse = True, sortNone = True)
    Example Input: sort([1, 3, 2, 5, 4, None, 7], sortNone = None)
    """

    return sorted(filter(lambda item: True if (sortNone != None) else (item != None), myList), 
        key = lambda item: (((item is None)     if (reverse) else (item is not None)) if (sortNone) else
                            ((item is not None) if (reverse) else (item is None)), item), 
        reverse = reverse)

这是一个如何运行它的示例:

myList = [1, 3, 2, 5, 4, None, 7]
print(sort(myList))
print(sort(myList, reverse = True))
print(sort(myList, sortNone = True))
print(sort(myList, reverse = True, sortNone = True))
print(sort(myList, sortNone = None))
print(sort(myList, reverse = True, sortNone = None))

【讨论】:

当你的函数变得那么大时,为什么不把它分解成一个合适的函数定义呢?将其保留为 lambda 只会让人难以阅读。

以上是关于排序列表,同时将 None 值推到最后的主要内容,如果未能解决你的问题,请参考以下文章

根据公共字符串将列表排序为列表,同时保留整个列表

04-python的列表操作

redis常用方法

如何在c#中保持内部顺序的同时将2个排序的列表合并到一个随机列表中

python 一个函数,它接受一个列表并将其分成n个段,同时将它们排序为列表字典。

Python 中的列表排序函数