我需要以下功能:
输入:list
输出:
True
如果输入列表中的所有元素使用标准相等运算符评估为彼此相等; False
否则。效果:当然,我不想招致任何不必要的开销。
我认为最好:
AND
所有生成的布尔值但我不确定Pythonic最常用的方法是什么。
修改:
谢谢你们所有的好答案。我评价了几个,在@KennyTM和@Ivo van der Wijk解决方案之间选择真的很难。
缺少短路功能只会对早期具有不相等元素的长输入(超过约50个元素)造成伤害。如果这种情况经常发生(通常取决于列表的长度),则需要进行短路。最好的短路算法似乎是@KennyTM checkEqual1
。然而,这为此付出了巨大的代价:
如果早期不等元素的长输入没有发生(或很少发生),则不需要短路。然后,到目前为止,最快的是@Ivo van der Wijk解决方案。
答案 0 :(得分:351)
一般方法:
def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == rest for rest in iterator)
一衬垫:
def checkEqual2(iterator):
return len(set(iterator)) <= 1
也是单行:
def checkEqual3(lst):
return lst[1:] == lst[:-1]
3个版本之间的区别在于:
checkEqual2
中,内容必须是可以播放的。checkEqual1
和checkEqual2
可以使用任何迭代器,但checkEqual3
必须接受序列输入,通常是列表或元组之类的具体容器。checkEqual1
就会停止。checkEqual1
包含更多Python代码,因此在开始时许多项目相同时效率较低。checkEqual2
和checkEqual3
始终执行O(N)复制操作,如果您的大部分输入都返回False,则会花费更长的时间。checkEqual2
和checkEqual3
,更难以适应从a == b
到a is b
的比较。 timeit
结果,对于Python 2.7和(只有s1,s4,s7,s9应该返回True)
s1 = [1] * 5000
s2 = [1] * 4999 + [2]
s3 = [2] + [1]*4999
s4 = [set([9])] * 5000
s5 = [set([9])] * 4999 + [set([10])]
s6 = [set([10])] + [set([9])] * 4999
s7 = [1,1]
s8 = [1,2]
s9 = []
我们得到了
| checkEqual1 | checkEqual2 | checkEqual3 | checkEqualIvo | checkEqual6502 |
|-----|-------------|-------------|--------------|---------------|----------------|
| s1 | 1.19 msec | 348 usec | 183 usec | 51.6 usec | 121 usec |
| s2 | 1.17 msec | 376 usec | 185 usec | 50.9 usec | 118 usec |
| s3 | 4.17 usec | 348 usec | 120 usec | 264 usec | 61.3 usec |
| | | | | | |
| s4 | 1.73 msec | | 182 usec | 50.5 usec | 121 usec |
| s5 | 1.71 msec | | 181 usec | 50.6 usec | 125 usec |
| s6 | 4.29 usec | | 122 usec | 423 usec | 61.1 usec |
| | | | | | |
| s7 | 3.1 usec | 1.4 usec | 1.24 usec | 0.932 usec | 1.92 usec |
| s8 | 4.07 usec | 1.54 usec | 1.28 usec | 0.997 usec | 1.79 usec |
| s9 | 5.91 usec | 1.25 usec | 0.749 usec | 0.407 usec | 0.386 usec |
注意:
# http://stackoverflow.com/q/3844948/
def checkEqualIvo(lst):
return not lst or lst.count(lst[0]) == len(lst)
# http://stackoverflow.com/q/3844931/
def checkEqual6502(lst):
return not lst or [lst[0]]*len(lst) == lst
答案 1 :(得分:261)
比使用set()更快的解决方案是在序列(不是迭代)上工作,它只是简单地计算第一个元素。这假设列表是非空的(但这很容易检查,并决定自己在空列表中应该是什么结果)
x.count(x[0]) == len(x)
一些简单的基准测试:
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*5000', number=10000)
1.4383411407470703
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*4999+[2]', number=10000)
1.4765670299530029
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*5000', number=10000)
0.26274609565734863
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*4999+[2]', number=10000)
0.25654196739196777
答案 2 :(得分:124)
最简单,最优雅的方式如下:
all(x==myList[0] for x in myList)
(是的,这甚至适用于空列表!这是因为这是python具有惰性语义的少数情况之一。)
关于性能,这将在尽可能早的时候失败,因此它是渐近最优的。
答案 3 :(得分:36)
一组比较工作:
len(set(the_list)) == 1
使用set
删除所有重复元素。
答案 4 :(得分:24)
您可以将列表转换为一组。一套不能有重复。因此,如果原始列表中的所有元素都相同,则该集合将只有一个元素。
if len(sets.Set(input_list)) == 1
// input_list has all identical elements.
答案 5 :(得分:15)
对于它的价值,这最近出现在python-ideas mailing list。事实证明,已经有itertools recipe这样做: 1
def all_equal(iterable):
"Returns True if all the elements are equal to each other"
g = groupby(iterable)
return next(g, True) and not next(g, False)
据说它表现得非常好,并且有一些不错的属性。
1 换句话说,我无法提出解决方案 - 即使找到也不能归功于我它
答案 6 :(得分:14)
将列表转换为集合时,将删除重复的元素。因此,如果转换后的集合的长度为1,则意味着所有元素都相同。
len(set(input_list))==1
这是一个例子
>>> a = ['not', 'the', 'same']
>>> b = ['same', 'same', 'same']
>>> len(set(a))==1 # == 3
False
>>> len(set(b))==1 # == 1
True
这会将输入列表的第一个元素与列表中的每个其他元素进行比较(等效)。如果相等,则返回True,否则返回False。
all(element==input_list[0] for element in input_list)
这是一个例子
>>> a = [1, 2, 3, 4, 5]
>>> b = [1, 1, 1, 1, 1]
>>> all(number==a[0] for number in a)
False
>>> all(number==b[0] for number in b)
True
P.S如果要检查整个列表是否等于某个值,则可以为input_list [0]设置该值。
答案 7 :(得分:10)
这是另一个选项,对于长列表(使用短路)比len(set(x))==1
更快
def constantList(x):
return x and [x[0]]*len(x) == x
答案 8 :(得分:7)
这是一种简单的方法:
result = mylist and all(mylist[0] == elem for elem in mylist)
这稍微复杂一点,它会产生函数调用开销,但语义更明确:
def all_identical(seq):
if not seq:
# empty list is False.
return False
first = seq[0]
return all(first == elem for elem in seq)
答案 9 :(得分:4)
如果你对一些更具可读性的东西感兴趣(但当然效率不高),你可以试试:
def compare_lists(list1, list2):
if len(list1) != len(list2): # Weed out unequal length lists.
return False
for item in list1:
if item not in list2:
return False
return True
a_list_1 = ['apple', 'orange', 'grape', 'pear']
a_list_2 = ['pear', 'orange', 'grape', 'apple']
b_list_1 = ['apple', 'orange', 'grape', 'pear']
b_list_2 = ['apple', 'orange', 'banana', 'pear']
c_list_1 = ['apple', 'orange', 'grape']
c_list_2 = ['grape', 'orange']
print compare_lists(a_list_1, a_list_2) # Returns True
print compare_lists(b_list_1, b_list_2) # Returns False
print compare_lists(c_list_1, c_list_2) # Returns False
答案 10 :(得分:4)
怀疑这是“最恐怖的”,但有点像:
>>> falseList = [1,2,3,4]
>>> trueList = [1, 1, 1]
>>>
>>> def testList(list):
... for item in list[1:]:
... if item != list[0]:
... return False
... return True
...
>>> testList(falseList)
False
>>> testList(trueList)
True
会做到这一点。
答案 11 :(得分:3)
关于将reduce()
与lambda
一起使用。这是一个我个人认为比其他一些答案更好的工作代码。
reduce(lambda x, y: (x[1]==y, y), [2, 2, 2], (True, 2))
返回一个truple,如果所有项目相同或不相同,则第一个值为布尔值。
答案 12 :(得分:3)
检查所有元素是否等于第一个元素。
np.allclose(array, array[0])
答案 13 :(得分:3)
将列表转换为集合,然后查找集合中的元素数量。如果结果为1,则它具有相同的元素,如果不是,则列表中的元素不相同。
list1 = [1,1,1]
len(set(list1))
>1
list1 = [1,2,3]
len(set(list1)
>3
答案 14 :(得分:3)
我会这样做:
not any((x[i] != x[i+1] for i in range(0, len(x)-1)))
any
一旦找到True
条件,就会停止搜索迭代。
答案 15 :(得分:2)
def allTheSame(i):
j = itertools.groupby(i)
for k in j: break
for k in j: return False
return True
适用于Python 2.4,它没有“全部”。
答案 16 :(得分:2)
可以使用map和lambda
lst = [1,1,1,1,1,1,1,1,1]
print all(map(lambda x: x == lst[0], lst[1:]))
答案 17 :(得分:2)
>>> a = [1, 2, 3, 4, 5, 6]
>>> z = [(a[x], a[x+1]) for x in range(0, len(a)-1)]
>>> z
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
# Replacing it with the test
>>> z = [(a[x] == a[x+1]) for x in range(0, len(a)-1)]
>>> z
[False, False, False, False, False]
>>> if False in z : Print "All elements are not equal"
答案 18 :(得分:1)
lambda lst: reduce(lambda a,b:(b,b==a[0] and a[1]), lst, (lst[0], True))[1]
下一个将短路:
all(itertools.imap(lambda i:yourlist[i]==yourlist[i+1], xrange(len(yourlist)-1)))
答案 19 :(得分:1)
你可以这样做:
reduce(and_, (x==yourList[0] for x in yourList), True)
令人讨厌的是python让你导入像operator.and_
这样的运算符。从python3开始,您还需要导入functools.reduce
。
(你不应该使用这种方法,因为如果找到不相等的值,它不会中断,但会继续检查整个列表。它只是作为完整性的答案包含在这里。)
答案 20 :(得分:1)
将列表更改为一组。然后,如果集合的大小只有1,它们必须是相同的。
if len(set(my_list)) == 1:
答案 21 :(得分:1)
还有一个纯Python递归选项:
def checkEqual(lst):
if len(lst)==2 :
return lst[0]==lst[1]
else:
return lst[0]==lst[1] and checkEqual(lst[1:])
但是,由于某些原因,在某些情况下它比其他选项要慢两个数量级。从C语言的心态来看,我期望这会更快,但事实并非如此!
另一个缺点是Python中存在递归限制,在这种情况下需要对其进行调整。例如,使用this。
答案 22 :(得分:1)
或使用numpy的diff
方法:
import numpy as np
def allthesame(l):
return np.all(np.diff(l)==0)
并致电:
print(allthesame([1,1,1]))
输出:
True
答案 23 :(得分:1)
或使用numpy的diff方法:
import numpy as np
def allthesame(l):
return np.unique(l).shape[0]<=1
并致电:
print(allthesame([1,1,1]))
输出:
是
答案 24 :(得分:1)
# script.awk is the one mentioned in James Brown's answer
# result here shown with GNU awk
$ time LC_ALL=C awk -f script.awk small.bam > f1
real 0m0.092s
# mawk is faster compared to GNU awk for this use case
$ time LC_ALL=C mawk -f script.awk small.bam > f2
real 0m0.054s
$ time perl -ne '$h{$&}++ if /CB:Z:\K[ACGT]++/; END{print "$_ $h{$_}\n" for keys %h}' small.bam > f3
real 0m0.064s
$ diff -sq <(sort f1) <(sort f2)
Files /dev/fd/63 and /dev/fd/62 are identical
$ diff -sq <(sort f1) <(sort f3)
Files /dev/fd/63 and /dev/fd/62 are identical
答案 25 :(得分:0)
您可以使用.nunique()
查找列表中唯一数量的项目。
def identical_elements(list):
series = pd.Series(list)
if series.nunique() == 1: identical = True
else: identical = False
return identical
identical_elements(['a', 'a'])
Out[427]: True
identical_elements(['a', 'b'])
Out[428]: False
答案 26 :(得分:0)
您可以使用set
。它将设置并删除重复的元素。然后检查其元素是否超过1个。
if len(set(your_list)) <= 1:
print('all ements are equal')
示例:
>>> len(set([5, 5])) <= 1
True
答案 27 :(得分:0)
也许我低估了这个问题?检查列表中唯一值的长度。
lzt = [1,1,1,1,1,2]
if (len(set(lzt)) > 1):
uniform = False
elif (len(set(lzt)) == 1):
uniform = True
elif (not lzt):
raise ValueError("List empty, get wrecked")
答案 28 :(得分:0)
我认为这是一个具有大量 Pythonicity 以及简单性和显而易见性的平衡的代码,它应该也适用于非常旧的 Python 版本。
def all_eq(lst):
for idx, itm in enumerate(lst):
if not idx: # == 0
prev = itm
if itm != prev:
return False
prev = itm
return True