check if all elements in a list are identical

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


check if all elements in a list are identical



I need the following function:



Input: a list


list



Output:


True


False



Performance: of course, I prefer not to incur any unnecessary overhead.



I feel it would be best to:


AND



But I'm not sure what's the most Pythonic way to do that.



EDIT:



Thank you for all the great answers. I rated up several, and it was really hard to choose between @KennyTM and @Ivo van der Wijk solutions.



The lack of short-circuit feature only hurts on a long input (over ~50 elements) that have unequal elements early on. If this occurs often enough (how often depends on how long the lists might be), the short-circuit is required. The best short-circuit algorithm seems to be @KennyTM checkEqual1. It pays, however, a significant cost for this:


checkEqual1



If the long inputs with early unequal elements don't happen (or happen sufficiently rarely), short-circuit isn't required. Then, by far the fastest is @Ivo van der Wijk solution.





Equal as in a == b or identical as in a is b?
– kennytm
Oct 2 '10 at 7:35


a == b


a is b





Should the solution handle empty lists? If so, what should be returned?
– Doug
Oct 2 '10 at 7:43





Equal as in a == b. Should handle empty list, and return True.
– max
Oct 2 '10 at 8:21




21 Answers
21



General method:


def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == rest for rest in iterator)



One-liner:


def checkEqual2(iterator):
return len(set(iterator)) <= 1



Also one-liner:


def checkEqual3(lst):
return lst[1:] == lst[:-1]



The difference between the 3 versions are that:


checkEqual2


checkEqual1


checkEqual2


checkEqual3


checkEqual1


checkEqual1


checkEqual2


checkEqual3


checkEqual2


checkEqual3


a is b


a == b



timeit result, for Python 2.7 and (only s1, s4, s7, s9 should return True)


timeit


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 =



we get


| 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 |



Note:


# 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





@max: Yes. Note that 1 msec = 1000 usec.
– kennytm
Oct 2 '10 at 8:28





Don't forget memory usage analysis for very large arrays, a native solution which optimizes away calls to obj.__eq__ when lhs is rhs, and out-of-order optimizations to allow short circuiting sorted lists more quickly.
– Glenn Maynard
Oct 2 '10 at 8:31


obj.__eq__


lhs is rhs





Ivo van der Wijk has a better solution for sequences that's about 5 times faster than set and O(1) in memory.
– aaronasterling
Oct 2 '10 at 8:32







@AaronMcSmooth: Without being a criticism of this answer, it's telling that this answer will probably remain at four times the score of the other: not due to comparative value, but due to the common early-answer and popular-answer vote bias of this site.
– Glenn Maynard
Oct 2 '10 at 8:57





@TurtlesAreCute: What is the problem of [2,3,3,3]? checkEqual3 does correctly return False.
– kennytm
May 2 '16 at 11:25


[2,3,3,3]



A solution faster than using set() that works on sequences (not iterables) is to simply count the first element. This assumes the list is non-empty (but that's trivial to check, and decide yourself what the outcome should be on an empty list)


x.count(x[0]) == len(x)



some simple benchmarks:


>>> 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





OMG, this is 6 times faster than the set solution! (280 million elements/sec vs 45 million elements/sec on my laptop). Why??? And is there any way to modify it so that it short circuits (I guess not...)
– max
Oct 2 '10 at 9:18





I guess list.count has a highly optimized C implementation, and the length of the list is stored internally, so len() is cheap as well. There's not a way to short-circuit count() since you will need to really check all elements to get the correct count.
– Ivo van der Wijk
Oct 2 '10 at 10:01





Can I change it to: x.count(next(x)) == len(x) so that it works for any container x? Ahh.. nm, just saw that .count is only available for sequences.. Why isn't it implemented for other builtin containers? Is counting inside a dictionary inherently less meaningful than inside a list?
– max
Oct 5 '10 at 5:09




x.count(next(x)) == len(x)





An iterator may not have a length. E.g. it can be infinite or just dynamically generated. You can only find its length by converting it to a list which takes away most of the iterators advantages
– Ivo van der Wijk
Oct 5 '10 at 5:51





Sorry, what I meant was why count isn't implemented for iterables, not why len isn't available for iterators. The answer is probably that it's just an oversight. But it's irrelavant for us because default .count() for sequences is very slow (pure python). The reason your solution is so fast is that it relies on the C-implemented count provided by list. So I suppose whichever iterable happens to implement count method in C will benefit from your approach.
– max
Mar 12 '16 at 3:36


count


len


.count()


count


list


count



The simplest and most elegant way is as follows:


all(x==myList[0] for x in myList)



(Yes, this even works with the null list! This is because this is one of the few cases where python has lazy semantics.)



Regarding performance, this will fail at the earliest possible time, so it is asymptotically optimal.





This works, but it's a bit (1.5x) slower than @KennyTM checkEqual1. I'm not sure why.
– max
Apr 24 '12 at 17:20


checkEqual1





max: Likely because I did not bother to perform the optimization first=myList[0] all(x==first for x in myList), perhaps
– ninjagecko
Nov 17 '15 at 12:48


first=myList[0]


all(x==first for x in myList)





I think that myList[0] is evaluated with each iteration. >>> timeit.timeit('all([y == x[0] for y in x])', 'x=[1] * 4000', number=10000) 2.707076672740641 >>> timeit.timeit('x0 = x[0]; all([y == x0 for y in x])', 'x=[1] * 4000', number=10000) 2.0908854261426484
– Matt Liberty
Jan 11 '16 at 21:35







I should of course clarify that the optimization first=myList[0] will throw an IndexError on an empty list, so commenters who were talking about that optimization I mentioned will have to deal with the edge-case of an empty list. However the original is fine (x==myList[0] is fine within the all because it is never evaluated if the list is empty).
– ninjagecko
Jan 13 '16 at 10:45




first=myList[0]


IndexError


x==myList[0]


all





This is clearly the right way to to it. If you want speed in every case, use something like numpy.
– Henry Gomersall
May 6 '16 at 16:14



A set comparison work:


len(set(the_list)) == 1



Using set removes all duplicate elements.


set





pythonic solution!!! :)
– MrRobot
Dec 22 '17 at 10:34



You can convert the list to a set. A set cannot have duplicates. So if all the elements in the original list are identical, the set will have just one element.


if len(sets.Set(input_list)) == 1
// input_list has all identical elements.





this is nice but it doesn't short circuit and you have to calculate the length of the resulting list.
– aaronasterling
Oct 2 '10 at 7:44







why not just len(set(input_list)) == 1?
– Nick Dandoulakis
Oct 2 '10 at 7:50


len(set(input_list)) == 1





@codaddict. It means that even if the first two elements are distinct, it will still complete the entire search. it also uses O(k) extra space where k is the number of distinct elements in the list.
– aaronasterling
Oct 2 '10 at 7:58







@max. because building the set happens in C and you have a bad implementation. You should at least do it in a generator expression. See KennyTM's answer for how to do it correctly without using a set.
– aaronasterling
Oct 2 '10 at 8:20





sets.Set is "Deprecated since version 2.6: The built-in set/frozenset types replace this module." (from docs.python.org/2/library/sets.html)
– Moberg
Jan 19 '17 at 22:23





For what it's worth, this came up on the python-ideas mailing list recently. It turns out that there is an itertools recipe for doing this already: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)



Supposedly it performs very nicely and has a few nice properties.



1In other words, I can't take the credit for coming up with the solution -- nor can I take credit for even finding it.





Much faster than the fastest answer listed here in the worst case scenario.
– ChaimG
Apr 29 at 23:32





This is another option, faster than len(set(x))==1 for long lists (uses short circuit)


len(set(x))==1


def constantList(x):
return x and [x[0]]*len(x) == x





It is 3 times slower than the set solution on my computer, ignoring short circuit. So if the unequal element is found on average in the first third of the list, it's faster on average.
– max
Oct 2 '10 at 9:21



This is a simple way of doing it:


result = mylist and all(mylist[0] == elem for elem in mylist)



This is slightly more complicated, it incurs function call overhead, but the semantics are more clearly spelled out:


def all_identical(seq):
if not seq:
# empty list is False.
return False
first = seq[0]
return all(first == elem for elem in seq)





You can avoid a redundant comparison here by using for elem in mylist[1:]. Doubt it improves speed much though since I guess elem[0] is elem[0] so the interpreter can probably do that comparison very quickly.
– Brendan
Jan 5 '17 at 15:58




for elem in mylist[1:]


elem[0] is elem[0]



Doubt this is the "most Pythonic", but something like:


>>> 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



would do the trick.





Your for loop can be made more Pythonic into if any(item != list[0] for item in list[1:]): return False, with exactly the same semantics.
– musiphil
Aug 18 '16 at 20:59


for


if any(item != list[0] for item in list[1:]): return False



I'd do:


not any((x[i] != x[i+1] for i in range(0, len(x)-1)))



as any stops searching the iterable as soon as it finds a True condition.


any


True





You don't need the extra parentheses around the generator expression if it's the only argument.
– ninjagecko
Apr 23 '12 at 17:02





so does all(), why not use all(x == seq[0] for x in seq) ? looks more pythonic and should perform the same
– Chen A.
Sep 4 '17 at 7:36


all()


all(x == seq[0] for x in seq)



If you're interested in something a little more readable (but of course not as efficient,) you could try:


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





I'm actually trying to see if all elements in one list are identical; not if two separate lists are identical.
– max
Jun 5 '12 at 22:22



Regarding using reduce() with lambda. Here is a working code that I personally think is way nicer than some of the other answers.


reduce()


lambda


reduce(lambda x, y: (x[1]==y, y), [2, 2, 2], (True, 2))



Returns a truple where the first value is the boolean if all items are same or not.



Check if all elements equal to the first.



np.allclose(array, array[0])


np.allclose(array, array[0])



Convert the list into the set and then find the number of elements in the set. If the result is 1, it has identical elements and if not, then the elements in the list are not identical.


list1 = [1,1,1]
len(set(list1))
>1

list1 = [1,2,3]
len(set(list1)
>3


>>> 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"


def allTheSame(i):
j = itertools.groupby(i)
for k in j: break
for k in j: return False
return True



Works in Python 2.4, which doesn't have "all".





for k in j: break is equivalent to next(j). You could also have done def allTheSame(x): return len(list(itertools.groupby(x))<2) if you did not care about efficiency.
– ninjagecko
Apr 23 '12 at 17:06


for k in j: break


next(j)


def allTheSame(x): return len(list(itertools.groupby(x))<2)



Can use map and lambda


lst = [1,1,1,1,1,1,1,1,1]

print all(map(lambda x: x == lst[0], lst[1:]))



You can do:


reduce(and_, (x==yourList[0] for x in yourList), True)



It is fairly annoying that python makes you import the operators like operator.and_. As of python3, you will need to also import functools.reduce.


operator.and_


functools.reduce



(You should not use this method because it will not break if it finds non-equal values, but will continue examining the entire list. It is just included here as an answer for completeness.)





This wouldn't short circuit. Why would you prefer it over your other solution?
– max
Apr 24 '12 at 17:18





@max: you wouldn't, precisely for that reason; I included it for the sake of completeness. I should probably edit it to mention that, thanks.
– ninjagecko
Apr 24 '12 at 17:39


lambda lst: reduce(lambda a,b:(b,b==a[0] and a[1]), lst, (lst[0], True))[1]



The next one will short short circuit:


all(itertools.imap(lambda i:yourlist[i]==yourlist[i+1], xrange(len(yourlist)-1)))





Your first code was obviously wrong: reduce(lambda a,b:a==b, [2,2,2]) yields False... I edited it, but this way it's not pretty anymore
– berdario
Mar 27 '14 at 9:41


reduce(lambda a,b:a==b, [2,2,2])


False





@berdario Then you should have written your own answer, rather than changing what somebody else wrote. If you think this answer was wrong, you can comment on it and/or downvote it.
– Gorpik
Mar 27 '14 at 9:47





It's better to fix something wrong, than leave it there for all the people to read it, possibly missing out the comments that explain why that was wrong
– berdario
Mar 27 '14 at 12:04





"When should I edit posts?" "Any time you feel you can make the post better, and are inclined to do so. Editing is encouraged!"
– berdario
Mar 27 '14 at 12:06



Change the list to a set. Then if the size of the set is only 1, they must have been the same.


if len(set(my_list)) == 1:



Here are two simple ways of doing this



When converting the list to a set, duplicate elements are removed. So if the length of the converted set is 1, then this implies that all the elements are the same.


len(set(input_list))==1



Here is an example


>>> a = ['not', 'the', 'same']
>>> b = ['same', 'same', 'same']
>>> len(set(a))==1 # == 3
False
>>> len(set(b))==1 # == 1
True



This will compare (equivalence) the first element of the input list to every other element in the list. If all are equivalent True will be returned, otherwise False will be returned.


all(element==input_list[0] for element in input_list)



Here is an example


>>> 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 If you are checking to see if the whole list is equivalent to a certain value, you can suibstitue the value in for input_list[0].






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Arduino Mega cannot recieve any sketches, stk500_recv() programmer is not responding

Visual Studio Code: How to configure includePath for better IntelliSense results

C++ virtual function: Base class function is called instead of derived