Programing

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

lottogame 2020. 3. 2. 13:00
반응형

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


다음 기능이 필요합니다.

입력 :list

출력 :

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

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

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

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

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


편집 :

모든 위대한 답변에 감사드립니다. 나는 여러 등급을 매겼으며 @KennyTM와 @Ivo van der Wijk 솔루션 중에서 선택하기가 정말 어려웠다.

단락 기능이 없으면 초기 요소가 같지 않은 긴 입력 (~ 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]에 대한 값을 사용할 수 있습니다.


이 방법은 len(set(x))==1긴 목록 보다 빠릅니다 (단락 사용).

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

이것은 간단한 방법입니다.

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)

모든 요소가 첫 번째 요소와 같은지 확인하십시오.

np.allclose(array, array[0])


의심 할 여지없이 이것은 "가장 파이썬적인"것입니다.

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

트릭을 할 것입니다.


좀 더 읽기 쉬운 (물론 효율적이지 않은) 것에 관심이 있다면 다음을 시도해보십시오.

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

나는 할 것이다 :

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

조건을 any찾으면 iterable 검색 중지 True합니다.


reduce()with를 사용 하는 경우 lambda. 여기 개인적으로 생각하는 작동 코드가 다른 답변보다 훨씬 좋습니다.

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

모든 항목이 같거나 같지 않은 경우 첫 번째 값이 부울 인 truple을 반환합니다.


목록을 세트로 변환 한 다음 세트의 요소 수를 찾으십시오. 결과가 1이면 동일한 요소가 있고 그렇지 않으면 목록의 요소가 동일하지 않습니다.

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

"모두"가없는 Python 2.4에서 작동합니다.


지도와 람다를 사용할 수 있습니다

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

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

또는 diffnumpy의 방법을 사용하십시오 .

import numpy as np
def allthesame(l):
    return np.all(np.diff(l)==0)

그리고 전화 :

print(allthesame([1,1,1]))

산출:

True

또는 numpy의 diff 방법을 사용하십시오.

import numpy as np
def allthesame(l):
    return np.unique(l).shape[0]<=1

그리고 전화 :

print(allthesame([1,1,1]))

산출:

진실


넌 할 수있어:

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

파이썬으로 연산자를 가져올 수 있다는 것은 상당히 성가신 일입니다 operator.and_. python3부터는을 가져와야 functools.reduce합니다.

(이 방법은 같지 않은 값을 찾으면 깨지지 않지만 전체 목록을 계속 검토하므로이 방법을 사용하면 안됩니다.이 방법은 완전성에 대한 답변으로 여기에 포함됩니다.)


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

목록을 세트로 변경하십시오. 그런 다음 세트의 크기가 1 인 경우 동일해야합니다.

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

순수한 파이썬 재귀 옵션도 있습니다.

 def checkEqual(lst):
    if len(lst)==2 :
        return lst[0]==lst[1]
    else:
        return lst[0]==lst[1] and checkEqual(lst[1:])

그러나 어떤 이유로 든 어떤 경우에는 다른 옵션보다 두 배의 속도가 느립니다. C 언어 사고 방식에서 나는 이것이 더 빠를 것으로 예상했지만 그렇지 않습니다!

다른 단점은 파이썬에는 재귀 제한이 있으며이 경우 조정해야한다는 것입니다. 예를 들어 this 를 사용 하십시오 .


.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

당신은 set그것을 사용 하고 반복적 인 요소를 제거 할 수 있습니다 . 그런 다음 1 요소가 있는지 확인하십시오.

if set(your_list) == 1:
    print('all ements are equal')

참고 URL : https://stackoverflow.com/questions/3844801/check-if-all-elements-in-a-list-are-identical



반응형