파이썬에는 순서가 있습니까? 있습니다. 주문 세트는 어떻습니까?

파이썬에는 사전이 있습니다. 주문 세트는 어떻습니까?



답변

이것에 대한 순서화 된 세트 (가능한 새로운 링크 ) 레시피가 있으며, 이는 Python 2 Documentation 에서 참조됩니다 . Py2.6 이상 및 3.0 이상에서 수정없이 실행됩니다. 인터페이스는 초기화를 목록으로 수행해야한다는 점을 제외하면 일반 세트와 거의 동일합니다.

OrderedSet([1, 2, 3])

이것은 MutableSet이므로에 대한 서명 .union이 세트 의 서명 과 일치하지 않지만 __or__비슷한 것을 포함하기 때문에 쉽게 추가 할 수 있습니다.

@staticmethod
def union(*sets):
    union = OrderedSet()
    union.union(*sets)
    return union

def union(self, *sets):
    for set in sets:
        self |= set


답변

정렬 된 집합은 기능적으로 정렬 된 사전의 특수한 경우입니다.

사전의 키는 고유합니다. 따라서 정렬 된 사전에서 값을 무시하면 (예 : 값을 할당하여 None) 본질적으로 정렬 된 세트를 갖습니다.

파이썬 3.1으로 있다 collections.OrderedDict. 다음은 OrderedSet의 구현 예입니다. (단 몇 가지 방법을 정의 또는 오버라이드 (override) 할 필요가 있습니다 : collections.OrderedDictcollections.MutableSet. 무거운 리프팅을 할)

import collections

class OrderedSet(collections.OrderedDict, collections.MutableSet):

    def update(self, *args, **kwargs):
        if kwargs:
            raise TypeError("update() takes no keyword arguments")

        for s in args:
            for e in s:
                 self.add(e)

    def add(self, elem):
        self[elem] = None

    def discard(self, elem):
        self.pop(elem, None)

    def __le__(self, other):
        return all(e in other for e in self)

    def __lt__(self, other):
        return self <= other and self != other

    def __ge__(self, other):
        return all(e in self for e in other)

    def __gt__(self, other):
        return self >= other and self != other

    def __repr__(self):
        return 'OrderedSet([%s])' % (', '.join(map(repr, self.keys())))

    def __str__(self):
        return '{%s}' % (', '.join(map(repr, self.keys())))

    difference = __sub__ 
    difference_update = __isub__
    intersection = __and__
    intersection_update = __iand__
    issubset = __le__
    issuperset = __ge__
    symmetric_difference = __xor__
    symmetric_difference_update = __ixor__
    union = __or__


답변

대답은 아니오이지만 동일한 목적 collections.OrderedDict으로 키 (및 값 None) 만으로 Python 표준 라이브러리에서 사용할 수 있습니다 .

업데이트 : Python 3.7 (및 CPython 3.6)부터 표준 dict순서를 유지하도록 보장되며 보다 성능이 뛰어납니다 OrderedDict. 그러나 이전 버전과의 호환성 및 특히 가독성을 위해 계속해서 사용하는 것이 OrderedDict좋습니다.

다음 dict은 주문을 유지하면서 중복 항목을 필터링하여 주문 세트를 에뮬레이트하는 주문 세트 로 사용하는 방법의 예입니다 . 사용 dict클래스 메소드를 fromkeys()다음 단순히 요청하는 딕셔너리를 만드는 keys()다시.

>>> keywords = ['foo', 'bar', 'bar', 'foo', 'baz', 'foo']

>>> list(dict.fromkeys(keywords))
['foo', 'bar', 'baz']


답변

나는 당신에게 OrderedSet보다 하나 더 잘 할 수 있습니다 : boltons는 순서가 지정된 세트 일뿐 만 아니라 색인을 지원 하는 순수한 파이썬, 2/3 호환 IndexedSet유형 을 가지고 있습니다 (목록과 마찬가지로).

간단하게 pip install boltons(또는 setutils.py코드베이스에 복사 ) 및를 가져옵니다 IndexedSet.

>>> from boltons.setutils import IndexedSet
>>> x = IndexedSet(list(range(4)) + list(range(8)))
>>> x
IndexedSet([0, 1, 2, 3, 4, 5, 6, 7])
>>> x - set(range(2))
IndexedSet([2, 3, 4, 5, 6, 7])
>>> x[-1]
7
>>> fcr = IndexedSet('freecreditreport.com')
>>> ''.join(fcr[:fcr.index('.')])
'frecditpo'

모든 것이 독특하고 순서대로 유지됩니다. 전체 공개 : 나는 쓴 IndexedSet,하지만 그 또한 의미 문제가 있는지 할 수 있습니다에게 버그 나 . 🙂


답변

PyPI 구현

다른 사람들은 파이썬 (아직)에 삽입 순서 보존 세트의 내장 구현이 없다고 지적했지만이 질문에는 PyPI 에서 무엇을 찾을 수 있는지에 대한 답변이 누락되었다고 생각합니다 .

패키지가 있습니다 :

이러한 구현 중 일부는 Raymond Hettinger가 ActiveState에 게시 한 레시피를 기반으로하며 여기에 다른 답변에서도 언급되어 있습니다.

약간의 차이

  • 주문 세트 (버전 1.1)
    • 장점 : 인덱스에 의해 조회를 위해 O (1) (예 my_set[5])
  • oset (버전 0.1.3)
    • 장점 : O (1) remove(item)
    • 단점 : 인덱스 별 조회의 경우 분명히 O (n)

모두 구현은 O (1)에 대한이 add(item)__contains__(item)( item in my_set)를.


답변

정렬 된 순서를 유지하기 위해 정렬 된 집합을 사용하는 경우 PyPI에서 정렬 된 집합 구현을 사용해보십시오. sortedcontainers의 모듈은 제공 SortedSet의를 바로이 목적을 위해. 몇 가지 장점 : 순수 Python, 빠른 C 구현, 100 % 단위 테스트 적용 범위, 스트레스 테스트 시간.

pip를 사용하면 PyPI에서 쉽게 설치할 수 있습니다.

pip install sortedcontainers

할 수없는 경우 오픈 소스 리포지토리pip install 에서 sortedlist.py 및 sortedset.py 파일을 풀다운하면 됩니다.

설치 한 후에는 간단하게 다음을 수행 할 수 있습니다.

from sortedcontainers import SortedSet
help(SortedSet)

sortedcontainers 모듈은 여러 대체 구현과 성능 비교 를 유지합니다 .

Python의 bag 데이터 유형에 대한 질문 에는 bag을 효율적으로 구현하는 데 사용할 수 있는 SortedList 데이터 유형이 있습니다.


답변

코드에서 이미 팬더를 사용중인 경우이 기사에Index 표시된 것처럼 해당 객체는 정렬 된 세트처럼 동작 합니다.

기사의 예 :

indA = pd.Index([1, 3, 5, 7, 9])
indB = pd.Index([2, 3, 5, 7, 11])

indA & indB  # intersection
indA | indB  # union
indA - indB  # difference
indA ^ indB  # symmetric difference