[python] 목록의 모든 요소가 동일한 지 확인하십시오

다음 기능이 필요합니다.

입력 :list

출력 :

  • True 입력 목록의 모든 요소가 표준 항등 연산자를 사용하여 서로 같은 것으로 평가되는 경우;
  • False 그렇지 않으면.

공연 : 물론 불필요한 오버 헤드가 발생하지 않는 것을 선호합니다.

나는 그것이 최선일 것이라고 생각한다.

  • 목록을 반복
  • 인접한 요소를 비교
  • 그리고 AND모든 결과 부울 값

그러나 가장 파이썬적인 방법이 무엇인지 잘 모르겠습니다.


단락 기능이 없으면 초기 요소가 같지 않은 긴 입력 (~ 50 개 이상의 요소)에 대해서만 문제가됩니다. 이 문제가 자주 발생하는 경우 (목록의 길이에 따라 다름) 단락이 필요합니다. 최고의 단락 알고리즘은 @KennyTM 인 것 같습니다 checkEqual1. 그러나 이것에 대한 상당한 비용을 지불합니다.

  • 거의 동일한 성능의 목록에서 최대 20 배
  • 짧은 목록에서 최대 2.5 배 성능

초기에 같지 않은 요소를 가진 긴 입력이 발생하지 않거나 충분히 드물게 발생하는 경우 단락이 필요하지 않습니다. 그런 다음 @Ivo van der Wijk 솔루션이 가장 빠릅니다.



답변

일반적인 방법 :

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 가지 버전의 차이점은 다음과 같습니다.

  1. 에서 checkEqual2내용 해쉬해야합니다.
  2. checkEqual1그리고 checkEqual2어떤 반복자를 사용할 수 있지만,checkEqual3 일련의 입력, 목록 또는 튜플 같은 일반적으로 콘크리트 용기를 취해야합니다.
  3. checkEqual1 차이가 발견되는 즉시 중지합니다.
  4. checkEqual1더 많은 Python 코드가 포함되어 있기 때문에 처음에 많은 항목이 동일한 경우 효율성이 떨어집니다.
  5. 이후 checkEqual2checkEqual3항상 O (N) 복사 작업을 수행 할 귀하의 의견의 대부분은 False를 반환한다면, 그들은 오래 걸릴 수 있습니다.
  6. 의 경우 checkEqual2checkEqual3는에서 비교 적응하기 힘들어 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


답변

시퀀스 (반복 가능하지 않음)에서 작동하는 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


답변

가장 간단하고 우아한 방법은 다음과 같습니다.

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

(예, 이것은 빈 목록으로도 작동합니다! 이것은 파이썬이 게으른 의미를 가진 몇 안되는 경우 중 하나이기 때문입니다.)

성능과 관련하여 가능한 빠른 시간 내에 실패하므로 무조건 최적입니다.


답변

세트 비교 작업 :

len(set(the_list)) == 1

를 사용 set하면 모든 중복 요소가 제거됩니다.


답변

목록을 세트로 변환 할 수 있습니다. 세트는 복제본을 가질 수 없습니다. 따라서 원래 목록의 모든 요소가 동일하면 세트에는 하나의 요소 만 있습니다.

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


답변

가치있는 것을 위해, 이것은 최근 파이썬 아이디어 메일 링리스트 에 나타났습니다 . 이미이 작업을 수행 하는 itertools 레시피 가 있음이 밝혀졌습니다 . 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. 단락 : 첫 번째 같지 않은 항목을 찾 자마자 iterable에서 항목 소비를 중지합니다.
  2. 항목을 해시 가능하지 않아도됩니다.
  3. 게으 르며 검사를 수행하기 위해 O (1) 추가 메모리 만 필요합니다.

1 다시 말해, 솔루션을 제공한다고해서 크레딧을받을 수 없으며 심지어 솔루션을 더라도 크레딧을받을 수 없습니다.


답변

이 작업을 수행하는 두 가지 간단한 방법이 있습니다.

set () 사용

목록을 세트로 변환 할 때 중복 요소가 제거됩니다. 따라서 변환 된 세트의 길이가 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

all () 사용

입력 목록의 첫 번째 요소를 목록의 다른 모든 요소와 비교 (등가)합니다. 모두 동등한 경우 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

PS 전체 목록이 특정 값과 같은지 확인하는 경우 input_list [0]에 대한 값을 사용할 수 있습니다.