我有两个长度相等的列表,一个包含数字,另一个包含None
。我想按降序排序,保持另一个同步。
在第二个列表只能包含字符串(所以没有None
元素)之前,我使用了这段代码:
weights, urls = zip(*sorted(zip(unordered_weights, unordered_urls), reverse=True))
数字在"权重"数组," urls"中的字符串;阵列。这很好。
但是,现在我在字符串列表中允许None
,我收到以下错误:
TypeError: unorderable types: str() < NoneType()
出于某种原因,它也试图对字符串进行排序,我想以防重量是相同的。我该如何解决这个问题?
我使用Python 3,我在Python 2 None
中读到任何字符串之前,但现在它给出了一个错误。具有相同权重的字符串顺序并不重要。
答案 0 :(得分:5)
按字典顺序排序元组 - 首先比较第一个元素,如果它们等于第二个元素,则在你的情况下可以是None
。您可以通过sorted()
的{{3}}参数将其作为排序键提取,仅使用权重进行排序:
weights, urls = zip(*sorted(zip(unordered_weights, unordered_urls), reverse=True, key=lambda x: x[0]))
观察:
In [1]: unordered_urls = ['b', 'a', None, 'c', None]
In [2]: unordered_weights = [1, 0, 0, 5, 2] # the 'a' and None have the same weight
In [3]: weights, urls = zip(*sorted(zip(unordered_weights, unordered_urls), reverse=True))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-61fb3631580a> in <module>()
----> 1 weights, urls = zip(*sorted(zip(unordered_weights, unordered_urls), reverse=True))
TypeError: unorderable types: str() < NoneType()
In [4]: weights, urls = zip(*sorted(zip(unordered_weights, unordered_urls), reverse=True, key=lambda x: x[0]))
In [5]: weights
Out[5]: (5, 2, 1, 0, 0)
In [6]: urls
Out[6]: ('c', None, 'b', 'a', None)
答案 1 :(得分:4)
如果第一个元素在两个元组之间相等,Python将在每个元组中使用第二个元素(您的字符串或None
值):
>>> (42, 'foo') < (42, None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() < NoneType()
你可以插一个打破平局:
from itertools import count
weights, __, urls = zip(*sorted(zip(unordered_weights, count(), unordered_urls), reverse=True))
count()
iterable object将从0
开始插入整数;当两个权重相同时,Python将比较这些整数。由于它们总是不同,因此第3位的元素永远不会相互比较。由于计数单调增加,因此排序保持稳定,否则两个具有相同权重的元素将保持相同的相对顺序。
或者你可以告诉sorted()
只看第一个元素:
from operator import itemgetter
weights, urls = zip(*sorted(zip(unordered_weights, unordered_urls),
reverse=True, key=itemgetter(0)))
现在两个相同的权重也保持相同的顺序,因为Python排序算法(TimSort)默认是稳定的。