Python:基于第一种无类型排序两个列表

时间:2016-04-12 16:52:16

标签: python list sorting python-3.x nonetype

所以我有两个清单:

keys   = ['Z', 'X', None, None]
values = [ 0 ,  1 , None, None]

我需要能够获取这两个列表并根据键值对它们进行排序,然后将其返回给自己。理想情况下,输出将是:

keys   = ['X', 'Z', None, None]
values = [ 1 ,  0 , None, None]

我在这里尝试的是:

self.keys, self.values = (list(x) for x in zip(*sorted(zip(self.keys, 
                          self.values), key=lambda pair: pair[0])))

这很好用,除了它给我的错误:

TypeError: unorderable types: NoneType() < str()

如何使用此方法对无进行排序?有没有比我尝试更好的方法?

5 个答案:

答案 0 :(得分:2)

链接的问题有一些可行的方法,但我认为错过了我喜欢的方法,即排序元组键而不是标量。这样我们就可以确保我们只是比较可比数量。

例如:

>>> list(zip(keys, values))
[('Z', 0), ('X', 1), (None, None), (None, None)]
>>> sorted(zip(keys, values),key=lambda x: (x[0] is None, x[0]))
[('X', 1), ('Z', 0), (None, None), (None, None)]

这是有效的,因为对于每一对,我们得到一个bool和一个字符串的元组:

>>> for pair in zip(keys, values):
...     print(pair, (pair[0] is None, pair[0]))
...     
('Z', 0) (False, 'Z')
('X', 1) (False, 'X')
(None, None) (True, None)
(None, None) (True, None)

由于元组比较如何工作,我们只需要在True或False组内进行比较,因此None永远不会与字符串进行比较。并且因为False&lt;没错,我们最后会得到None对。

答案 1 :(得分:0)

如果你需要让你的排序键功能在返回值上保持一致(如果没有,你应该),只需像lambda pair: pair[0] or ""一样修改它。它会在""上返回(None, <WHATEVER>)

否则请定义是否None > "1"

答案 2 :(得分:0)

只需为sorted

的密钥添加条件
keys, values = (list(x) for x in zip(*sorted(zip(keys, values), key=lambda pair: pair[0] if pair[0] is not None else 'temp')))

这样做地图&#39; temp&#39;列表中的任何无值以及排序&#39; temp&#39;的比较顺序大于&#39;。大写字母小于小写

>>> 'temp' < 'X'
False

答案 3 :(得分:0)

另一个解决方案是让某个对象永远不会比任何其他对象更小,并在遇到None时将其用于比较。

>>> def sortkey(pair):
...     if pair[0] is not None:
...         return pair[0]
...     return type('', (object,), {'__lt__': lambda x,y: False})()
... 
>>> keys   = ['Z', 'X', None, None]
>>> values = [ 0 ,  1 , None, None]
>>> k, v = map(list, zip(*sorted(zip(keys, values), key=sortkey)))
>>> k
['X', 'Z', None, None]
>>> v
[1, 0, None, None]

答案 4 :(得分:0)

一个简单的解决方案将涉及定义您自己的密钥

sort_fxn = lambda pair: '' if pair[0] is None else pair[0] 
list(zip(*sorted(zip(keys, values), key=sort_fxn)))

“无”值不位于排序的末尾,而是对其他键进行排序:

[(None, None, 'X', 'Z'), (None, None, 1, 0)]

如果使用None值对排序至关重要,可以将所有字符串编码为字节并使用字节数组比较:

sort_fxn = lambda pair: bytes([255]) if pair[0] is None else pair[0].encode('utf-8')

注意:由于排序,排序需要两倍的时间。 (3 vs 1.5微秒)如果你担心这种优化。