所以在Python 2中你可以使用像
这样的东西>>> items = [[1, 2], [3], [3], 4, 'a', 'b', 'a']
>>> from itertools import groupby
>>> [k for k, g in groupby(sorted(items))]
[4, [1, 2], [3], 'a', 'b']
在O(N log N)
时间内效果很好。然而,Python 3感叹TypeError: unorderable types: int() < list()
。那么在Python 3中实现它的最佳方法是什么? (我知道最好是一个主观的术语,但实际上根据Python应该有一种方法)
答案 0 :(得分:5)
在2.x中,两个无法比较的内置类型的值按类型排序。除了在解释器的一次运行期间它将保持一致时,不定义类型的顺序。因此,2 < [2]
可能是真或假,但始终是真还是假。
在3.x中,无法比较的内置类型的值是无法比拟的 - 这意味着如果您尝试比较它们,它们会引发TypeError
。所以,2 < [2]
是一个错误。并且,至少从3.3开始,类型本身甚至不具有可比性。但是,如果您想要重现的只是2.x行为,那么它们的id
绝对可以比较,并且在解释器运行期间是一致的。所以:
sorted(items, key=lambda x: (id(type(x)), x))
对于您的用例,这就是您所需要的一切。
然而,这与2.x所做的完全不同,因为这意味着,例如,1.5 < 2
可能是False
(因为float
&gt; { {1}})。如果要复制确切的行为,则需要编写首先尝试比较值的键函数,然后在int
上回退以比较类型。
这是少数几种情况之一,旧式TypeError
函数比新式cmp
函数更容易阅读,所以让我们写一个,然后使用{{ 3}}在它上面:
key
这仍然不能保证2.x给出的两个不同类型的值之间的顺序相同,但由于2.x没有定义任何这样的顺序(只是它在一次运行中是一致的),所以没有办法它可以。
然而,还有一个真正的缺陷:如果你定义一个对象没有完全排序的类,它们最终会排序相同,我不确定这是2.x会做的同样的事情。那种情况。
答案 1 :(得分:1)
让我们退后一步。
您想要统一集合。
如果值是可清除的,则使用O(N)set
解决方案。但他们不是。如果您可以提出某种哈希函数,则可以等效地使用dict
myhash(value): value
。如果您的用例确实“只有可缓存的值和平坦的list
可散列值”,则可以try
hash
执行此操作,然后再回到hash(tuple())
}。但总的来说,这不会起作用。
如果它们是完全有序的,您将使用O(N log N)sorted
解决方案(或等效的,基于树的解决方案或类似方法)。如果您可以提出某种完整排序功能,则可以将key
传递给sorted
函数。我认为这将适用于您的用例(因此我的另一个答案)。但是,如果没有,那么O(N log N)解决方案就不会起作用了。
如果它们都不是,你可以回到O(N ** 2)线性搜索解决方案:
unique = []
for value in items:
if value not in unique:
unique.append(value)
如果找不到某种方法来定义值的完整排序或散列函数,那么这是你能做到的最好的。