Python:根据第一个 None 类型对两个列表进行排序
Python: Sort Two Lists Based On First With None Types
所以我有两个列表:
keys = ['Z', 'X', None, None]
values = [ 0 , 1 , None, None]
我需要能够获取这两个列表并根据键值对它们进行排序,然后 return 它自己。理想情况下,输出为:
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()
如何使用此方法对 None 进行排序?有比我尝试的更好的方法吗?
如果您需要让您的排序键函数在 return 值上保持一致(如果不是,您应该这样做),只需将其修改为 lambda pair: pair[0] or ""
。它将在 (None, <WHATEVER>)
.
return ""
否则请定义是否None > "1"
。
只需为 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')))
这样做会将 'temp' 映射到列表中的任何 None 值,并且按排序的比较顺序 'temp' 大于 'X'。大写字母小于小写字母
>>> 'temp' < 'X'
False
链接的问题有一些可行的方法,但我认为错过了我的首选方法,即按 元组 键而不是标量进行排序。这样我们就可以确保我们只比较可比较的数量。
例如:
>>> 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)]
这是有效的,因为对于每一对,我们得到一个布尔值和一个字符串的元组:
>>> 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 < True,我们将在最后得到 None 对。
另一种解决方案是拥有一些永远不会小于任何其他对象的对象,并在遇到 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]
一个简单的解决方案是定义您自己的密钥
sort_fxn = lambda pair: '' if pair[0] is None else pair[0]
list(zip(*sorted(zip(keys, values), key=sort_fxn)))
None 值未位于排序的末尾,但其他键已排序:
[(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 对 1.5 微秒)如果您担心这种优化。
所以我有两个列表:
keys = ['Z', 'X', None, None]
values = [ 0 , 1 , None, None]
我需要能够获取这两个列表并根据键值对它们进行排序,然后 return 它自己。理想情况下,输出为:
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()
如何使用此方法对 None 进行排序?有比我尝试的更好的方法吗?
如果您需要让您的排序键函数在 return 值上保持一致(如果不是,您应该这样做),只需将其修改为 lambda pair: pair[0] or ""
。它将在 (None, <WHATEVER>)
.
""
否则请定义是否None > "1"
。
只需为 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')))
这样做会将 'temp' 映射到列表中的任何 None 值,并且按排序的比较顺序 'temp' 大于 'X'。大写字母小于小写字母
>>> 'temp' < 'X'
False
链接的问题有一些可行的方法,但我认为错过了我的首选方法,即按 元组 键而不是标量进行排序。这样我们就可以确保我们只比较可比较的数量。
例如:
>>> 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)]
这是有效的,因为对于每一对,我们得到一个布尔值和一个字符串的元组:
>>> 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 < True,我们将在最后得到 None 对。
另一种解决方案是拥有一些永远不会小于任何其他对象的对象,并在遇到 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]
一个简单的解决方案是定义您自己的密钥
sort_fxn = lambda pair: '' if pair[0] is None else pair[0]
list(zip(*sorted(zip(keys, values), key=sort_fxn)))
None 值未位于排序的末尾,但其他键已排序:
[(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 对 1.5 微秒)如果您担心这种优化。