programing

목록의 모든 요소가 고유한지 확인

mbctv 2023. 4. 11. 22:30
반응형

목록의 모든 요소가 고유한지 확인

목록의 모든 요소가 고유한지 여부를 확인하는 가장 좋은 방법(기존 방식대로)은 무엇입니까?

하고 있는 로는 ★★★★★★★★★★★」Counter 말합니다

>>> x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
>>> counter = Counter(x)
>>> for values in counter.itervalues():
        if values > 1: 
            # do something

더 잘할 수 있을까?

가장 효율적이지는 않지만 직설적이고 간결함:

if len(x) > len(set(x)):
   pass # do something

아마 최종 후보자에겐 큰 차이가 없을 거야

조기 퇴출도 할 수 있는 2개의 라이너가 있습니다.

>>> def allUnique(x):
...     seen = set()
...     return not any(i in seen or seen.add(i) for i in x)
...
>>> allUnique("ABCDEF")
True
>>> allUnique("ABACDEF")
False

가 해시 않은 의 목록을 seen:

>>> def allUnique(x):
...     seen = list()
...     return not any(i in seen or seen.append(i) for i in x)
...
>>> allUnique([list("ABC"), list("DEF")])
True
>>> allUnique([list("ABC"), list("DEF"), list("ABC")])
False

조기 종료 솔루션은 다음과 같습니다.

def unique_values(g):
    s = set()
    for x in g:
        if x in s: return False
        s.add(x)
    return True

, 나 조기 종료가 경우라면, 는 '조기 '를 합니다.len(x) != len(set(x))가장 빠른 방법입니다.

속도:

import numpy as np
x = [1, 1, 1, 2, 3, 4, 5, 6, 2]
np.unique(x).size == len(x)

모든 엔트리를 한 세트에 추가하여 길이를 확인하는 것은 어떻습니까?

len(set(x)) == len(x)

「 」의 대체 수단set , 을하면 됩니다.dict.

len({}.fromkeys(x)) == len(x)

정렬 및 그룹별을 사용하는 다른 접근 방식:

from itertools import groupby
is_unique = lambda seq: all(sum(1 for _ in x[1])==1 for x in groupby(sorted(seq)))

정렬이 필요하지만 처음 반복된 값으로 종료됩니다.

다음은 재미를 위한 재귀 O(N2) 버전입니다.

def is_unique(lst):
    if len(lst) > 1:
        return is_unique(s[1:]) and (s[0] not in s[1:])
    return True

다음은 재귀 조기 종료 함수입니다.

def distinct(L):
    if len(L) == 2:
        return L[0] != L[1]
    H = L[0]
    T = L[1:]
    if (H in T):
            return False
    else:
            return distinct(T)    

기능적인 어프로치를 하면서 이상한(느린) 변환을 하지 않아도 충분히 빠릅니다.

위의 답변은 모두 좋지만, 저는 python30초 예제를 사용하는 것을 선호합니다.

'어울리다'를 써야 요.set()중복을 제거할 특정 목록에서 해당 길이를 목록 길이와 비교합니다.

def all_unique(lst):
  return len(lst) == len(set(lst))

True의 모든 이 「」인 .unique,False렇지지그

x = [1, 2, 3, 4, 5, 6]
y = [1, 2, 2, 3, 4, 5]
all_unique(x)  # True
all_unique(y)  # False

제안 솔루션과 성능도를 비교해보니

len(lst) == len(set(lst))

가장 빠른 해결책입니다.목록에 초기 중복 항목이 있는 경우 선호되는 몇 가지 고정 시간 솔루션이 있습니다.

여기에 이미지 설명 입력

여기에 이미지 설명 입력


플롯을 재현하는 코드:

import perfplot
import numpy as np
import pandas as pd


def len_set(lst):
    return len(lst) == len(set(lst))


def set_add(lst):
    seen = set()
    return not any(i in seen or seen.add(i) for i in lst)


def list_append(lst):
    seen = list()
    return not any(i in seen or seen.append(i) for i in lst)


def numpy_unique(lst):
    return np.unique(lst).size == len(lst)


def set_add_early_exit(lst):
    s = set()
    for item in lst:
        if item in s:
            return False
        s.add(item)
    return True


def pandas_is_unique(lst):
    return pd.Series(lst).is_unique


def sort_diff(lst):
    return not np.any(np.diff(np.sort(lst)) == 0)


b = perfplot.bench(
    setup=lambda n: list(np.arange(n)),
    title="All items unique",
    # setup=lambda n: [0] * n,
    # title="All items equal",
    kernels=[
        len_set,
        set_add,
        list_append,
        numpy_unique,
        set_add_early_exit,
        pandas_is_unique,
        sort_diff,
    ],
    n_range=[2**k for k in range(18)],
    xlabel="len(lst)",
)

b.save("out.png")
b.show()

이건 어때?

def is_unique(lst):
    if not lst:
        return True
    else:
        return Counter(lst).most_common(1)[0][1]==1

의존관계에 데이터 처리 라이브러리가 있는 경우에만 원하는 부울값을 제공하는 솔루션이 이미 구현되어 있습니다.

import pandas as pd
pd.Series(lst).is_unique

Yan 구문(len(x)> len(set(x)))을 사용할 수 있지만 set(x) 대신 함수를 정의합니다.

 def f5(seq, idfun=None): 
    # order preserving
    if idfun is None:
        def idfun(x): return x
    seen = {}
    result = []
    for item in seq:
        marker = idfun(item)
        # in old Python versions:
        # if seen.has_key(marker)
        # but in new ones:
        if marker in seen: continue
        seen[marker] = 1
        result.append(item)
    return result

len(x) > len(f5(x))을 실행합니다.이 방법은 빠르고 주문 유지도 가능합니다.

코드는 http://www.peterbe.com/plog/uniqifiers-benchmark 에서 가져옵니다.

Panda 데이터 프레임에서 유사한 접근 방식을 사용하여 열의 내용이 고유한 값을 포함하는지 테스트하는 방법:

if tempDF['var1'].size == tempDF['var1'].unique().size:
    print("Unique")
else:
    print("Not unique")

이것은 100만 행이 넘는 날짜 프레임의 int 변수에서 즉시 발생합니다.

질문에 완전히 들어맞지는 않지만, 제가 부탁한 작업을 구글로 검색하면 이 질문이 1순위로 올라가고 쿼시톤의 연장선상에 있기 때문에 사용자가 관심을 가질 수 있습니다.각 목록 요소가 고유한지 여부를 조사하는 경우 다음을 수행할 수 있습니다.

import timeit
import numpy as np

def get_unique(mylist):
    # sort the list and keep the index
    sort = sorted((e,i) for i,e in enumerate(mylist))
    # check for each element if it is similar to the previous or next one    
    isunique = [[sort[0][1],sort[0][0]!=sort[1][0]]] + \
               [[s[1], (s[0]!=sort[i-1][0])and(s[0]!=sort[i+1][0])] 
                for [i,s] in enumerate (sort) if (i>0) and (i<len(sort)-1) ] +\
               [[sort[-1][1],sort[-1][0]!=sort[-2][0]]]     
    # sort indices and booleans and return only the boolean
    return [a[1] for a in sorted(isunique)]


def get_unique_using_count(mylist):
     return [mylist.count(item)==1 for item in mylist]

mylist = list(np.random.randint(0,10,10))
%timeit for x in range(10): get_unique(mylist)
%timeit for x in range(10): get_unique_using_count(mylist)

mylist = list(np.random.randint(0,1000,1000))
%timeit for x in range(10): get_unique(mylist)
%timeit for x in range(10): get_unique_using_count(mylist)

최종 리스트의 경우get_unique_using_count일부 답변에서 제시된 바와 같이 속도가 빠릅니다.그러나 목록이 이미 100개보다 긴 경우 카운트 함수는 상당히 오래 걸립니다.따라서 에 나타낸 접근법은get_unique기능이 더 복잡해 보이지만 훨씬 더 빠릅니다.

목록이 정렬된 경우 다음을 사용할 수 있습니다.

not any(sorted_list[i] == sorted_list[i + 1] for i in range(len(sorted_list) - 1))

꽤 효율적이긴 하지만, 이 목적을 위해 분류할 가치는 없습니다.

거지의 경우:

def AllDifferent(s):
    for i in range(len(s)):
        for i2 in range(len(s)):
            if i != i2:
                if s[i] == s[i2]:
                    return False
    return True

언급URL : https://stackoverflow.com/questions/5278122/checking-if-all-elements-in-a-list-are-unique

반응형