sorted key =不适用于子列表

时间:2011-04-17 20:26:41

标签: python sorting python-3.x

我正在编写单元测试,其中一个检查返回包含子列表[[],[],[]]的列表的方法,子列表的顺序与子列表的数量及其值无关,问题是不推荐使用TestCase.assertItemsEqual(),并且没有TestCase.assertElementsEqual()方法。为了解决这个问题,我决定对方法返回的列表和单元测试中的列表进行排序,并比较排序的版本,但问题是子列表总是有一个None值,排序会引发错误:

>>> sorted( [ [None], [1,2] ] )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < NoneType()

实际上我的子列表总是有8个值,其中一个是None,我有2到4个子列表。

所以,我写了一个小的lambda,将None更改为0,因为排序无关紧要,我只需要确保顺序是相同的:

>>> (lambda x: x if x is not None else 0)(None)
0
>>> (lambda x: x if x is not None else 0)(1)
1

但它不起作用,

>>> sorted( [ [None], [1,2] ], key = lambda x: x if x is not None else 0 )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < NoneType()

错误消息误导我认为将NoneType更改为IntType会修复,但我知道lambda中的x值是其中一个子列表,这就是lambda无法正常工作的原因。但我不知道如何解决它。

2 个答案:

答案 0 :(得分:0)

在Python 3中,异构比较不再“正常工作”。我认为这种变化的理由是它们会带来意想不到的结果。另外:我们无法再为自定义排序指定cmp函数。因此,我认为您正在尝试替换None值。

您可以将None值替换为0,如下所示:

L = [[None], [1, 2]]
normalized = list(list(0 if i is None else i for i in x) for x in L)
# list-comprehension alternative:
# L2 = [[0 if i is None else i for i in x] for x in L]

然后您可以使用assertEquals来比较已排序的列表:

expected_result = [[0], [1, 2]]
self.assertEquals(sorted(normalized), sorted(expected_result))

编辑:
当然可以优化以下内容,但如果你需要一个任意级别的嵌套解决方案,这是一个开始:

import collections
def replace_nested(L, replacement=0):
    if None in L:
        for i,item in enumerate(L):
            if item is None:
                L[i] = replacement
    else:
        for i,S in enumerate(L):
            if isinstance(S, collections.Iterable) and not isinstance(S, str):
                replace_nested(S)

答案 1 :(得分:0)

我在问到这个问题之后就把它弄好了,问题是传递给键函数的值是其中一个子列表,所以我只需要遍历子列表并将None更改为0,就像使用normalized一样,这就是我得到的:

# this sort a list with a sublist that has a None value in it - the None is changed to a 0 -
sort_none = lambda z: sorted( z, key= lambda x: [ 0 if y is None else y for y in x ] )
board = Board( [ 1,2,3 ,4,None,5 ,6,7,8 ] )
self.assertEqual( sort_none(board.valid_moves()),
    sort_none([
        [ 1,None,3 ,4,2,5 ,6,7,8],
        [ 1,2,3 ,None,4,5 ,6,7,8],
        [ 1,2,3 ,4,5,None ,6,7,8],
        [ 1,2,3, 4,7,5 ,6,None,8]
    ])
)

感谢您的时间