【问题标题】:sorted key= does not apply to sublistssorted key= 不适用于子列表
【发布时间】:2011-08-07 11:04:18
【问题描述】:

我正在编写一个单元测试,其中一个检查返回包含子列表[[],[],[]] 的列表的方法,子列表的顺序与子列表的数量及其值无关,问题是@ 987654322@ 已弃用,并且没有 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 不起作用的原因。但我不知道如何解决它。

【问题讨论】:

    标签: python sorting python-3.x


    【解决方案1】:

    在 Python 3 中,异构比较不再“正常工作”。我认为这种变化的基本原理是它们可能会返回意想不到的结果。另外:我们不能再为自定义排序指定cmp 函数。所以我认为你在尝试替换 None 值时走在正确的轨道上。

    您可以像这样用0 替换None 值:

    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)
    

    【讨论】:

      【解决方案2】:

      我刚问完问题就明白了,问题是传递给 key 函数的值是子列表之一,所以我只需要遍历子列表并将 None 更改为 0 就像你对规范化所做的那样,这是我得到的:

      # 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]
          ])
      )
      

      感谢您的宝贵时间

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-26
        • 2012-12-05
        • 1970-01-01
        • 2019-03-24
        • 1970-01-01
        • 2012-02-16
        • 2016-07-05
        • 2018-05-27
        相关资源
        最近更新 更多