所以我有两个清单:
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()
如何使用此方法对无进行排序?有没有比我尝试更好的方法?
答案 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微秒)如果你担心这种优化。