检查列表中的所有元素是否相同 [英] check if all elements in a list are identical

查看:95
本文介绍了检查列表中的所有元素是否相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要以下函数:



输入:a 列表 p>

输出




  • True 如果输入列表中的所有元素使用标准等式运算符计算为彼此相等;



效果:当然,我不希望产生任何不必要的开销。



我觉得最好:




  • 遍历列表

  • 比较相邻元素

  • AND 所有生成的布尔值



但我不知道什么是最坏的方式






EDIT

感谢所有伟大的答案。我给了几个评分,很难在@KennyTM和@Ivo van der Wijk解决方案之间选择。



缺少短路功能只会伤害长输入(超过〜50个元素),早期具有不等的元素。如果这种情况经常发生(多长时间取决于列表可能有多长时间),则需要短路。最好的短路算法似乎是@KennyTM checkEqual1 。但是,这样做的成本很高:




  • 性能几乎相同的列表中达到20倍

  • 短名单上效果最高可达2.5倍



如果具有早期不相等元素的长输入未发生足够少),不需要短路。然后,到目前为止,最快的是@Ivo van der Wijk解决方案。

解决方案

一般方法:



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


b $ b

一行:

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

还有一行:

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

这三个版本之间的区别是:


  1. code> checkEqual2 内容必须可哈希。

  2. checkEqual1 checkEqual2 可以使用任何迭代器,但 checkEqual3 必须接受序列输入,通常是具体容器,如列表或元组。
  3. $ b
  4. checkEqual1

  5. 由于 checkEqual2 包含更多的Python代码,因此效率较低。和 checkEqual3 始终执行O(N)复制操作,如果大部分输入将返回False,则它们将需要更长时间。

  6. checkEqual2 checkEqual3 不能轻易改为采用比较 a是b 而不是 a == 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毫秒| 348 usec | 183 usec | 51.6 usec | 121 usec |
| s2 | 1.17毫秒| 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毫秒| | 182 usec | 50.5 usec | 121 usec |
| s5 | 1.71毫秒| | 181 usec | 50.6 usec | 125 usec |
| s6 | 4.29 usec | | 122usec | 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 |

注意:

 code>#http://stackoverflow.com/q/3844948/ 
def checkEqualIvo(lst):
return not lst或lst.count(lst [0])== len )

#http://stackoverflow.com/q/3844931/
def checkEqual6502(lst):
return not lst或[lst [0]] * len )== lst


I need the following function:

Input: a list

Output:

  • True if all elements in the input list evaluate as equal to each other using the standard equality operator;
  • False otherwise.

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

I feel it would be best to:

  • iterate through the list
  • compare adjacent elements
  • and AND all the resulting Boolean values

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:

  • up to 20x in performance nearly-identical lists
  • up to 2.5x in performance on short lists

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.

解决方案

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:

  1. In checkEqual2 the content must be hashable.
  2. checkEqual1 and checkEqual2 can use any iterators, but checkEqual3 must take a sequence input, typically concrete containers like a list or tuple.
  3. checkEqual1 stops as soon as a difference is found.
  4. Since checkEqual1 contains more Python code, it is less efficient when many of the items are equal in the beginning.
  5. Since checkEqual2 and checkEqual3 always perform O(N) copying operations, they will take longer if most of your input will return False.
  6. checkEqual2 and checkEqual3 can't be easily changed to adopt to compare a is b instead of a == b.


timeit result, for Python 2.7 and (only s1, s4, s7, s9 should return 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 = []

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

这篇关于检查列表中的所有元素是否相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆