我需要一个函数,它接受一个列表并输出True,如果输入列表中的所有元素使用标准相等运算符计算彼此相等,否则输出False。
我觉得最好是遍历列表,比较相邻的元素,然后与所有结果布尔值。但我不知道最python的方法是什么。
我需要一个函数,它接受一个列表并输出True,如果输入列表中的所有元素使用标准相等运算符计算彼此相等,否则输出False。
我觉得最好是遍历列表,比较相邻的元素,然后与所有结果布尔值。但我不知道最python的方法是什么。
当前回答
将您的输入转换为一个集:
len(set(the_list)) <= 1
使用set可以删除所有重复的元素。<= 1使它在输入为空时正确地返回True。
这要求输入中的所有元素都是可哈希的。例如,如果传入一个列表的列表,就会得到一个TypeError。
其他回答
我怀疑这是“最python化的”,但类似于:
>>> 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
会成功的。
出现使用itertools。Groupby(参见itertools食谱):
from itertools import groupby
def all_equal(iterable):
g = groupby(iterable)
return next(g, True) and not next(g, False)
或不带groupby:
def all_equal(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == x for x in iterator)
您可以考虑使用许多其他的一行程序:
Converting the input to a set and checking that it only has one or zero (in case the input is empty) items def all_equal2(iterator): return len(set(iterator)) <= 1 Comparing against the input list without the first item def all_equal3(lst): return lst[:-1] == lst[1:] Counting how many times the first item appears in the list def all_equal_ivo(lst): return not lst or lst.count(lst[0]) == len(lst) Comparing against a list of the first element repeated def all_equal_6502(lst): return not lst or [lst[0]]*len(lst) == lst
但它们也有一些缺点,即:
all_equal and all_equal2 can use any iterators, but the others must take a sequence input, typically concrete containers like a list or tuple. all_equal and all_equal3 stop as soon as a difference is found (what is called "short circuit"), whereas all the alternatives require iterating over the entire list, even if you can tell that the answer is False just by looking at the first two elements. In all_equal2 the content must be hashable. A list of lists will raise a TypeError for example. all_equal2 (in the worst case) and all_equal_6502 create a copy of the list, meaning you need to use double the memory.
在Python 3.9中,使用perfplot,我们得到这些计时(越低的Runtime [s]越好):
如果你对一些更有可读性的东西感兴趣(但当然不是那么高效),你可以尝试:
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
比使用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
最佳答案
Twitter上有一个不错的帖子,介绍了实现all_equal()函数的各种方法。
给定一个列表输入,最好的提交是:
t.count(t[0]) == len(t)
其他方法
下面是线程的结果:
Have groupby() compare adjacent entries. This has an early-out for a mismatch, does not use extra memory, and it runs at C speed. g = itertools.groupby(s) next(g, True) and not next(g, False) Compare two slices offset from one another by one position. This uses extra memory but runs at C speed. s[1:] == s[:-1] Iterator version of slice comparison. It runs at C speed and does not use extra memory; however, the eq calls are expensive. all(map(operator.eq, s, itertools.islice(s, 1, None))) Compare the lowest and highest values. This runs at C speed, doesn't use extra memory, but does cost two inequality tests per datum. min(s) == max(s) # s must be non-empty Build a set. This runs at C speed and uses little extra memory but requires hashability and does not have an early-out. len(set(t))==1. At great cost, this handles NaNs and other objects with exotic equality relations. all(itertools.starmap(eq, itertools.product(s, repeat=2))) Pull out the first element and compare all the others to it, stopping at the first mismatch. Only disadvantage is that this doesn't run at C speed. it = iter(s) a = next(it, None) return all(a == b for b in it) Just count the first element. This is fast, simple, elegant. It runs at C speed, requires no additional memory, uses only equality tests, and makes only a single pass over the data. t.count(t[0]) == len(t)