답변:
이것에 대한 순서화 된 세트 (가능한 새로운 링크 ) 레시피가 있으며, 이는 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
update
, union
, intersection
.
union
같은 클래스에서 두 가지 메서드를 모두 호출 할 수는 없습니다 . 마지막은 "승리"하고 첫 번째는 런타임에 존재하지 않습니다. 이는 OrderedSet.union
(parens 없음) 단일 객체 를 참조해야 하기 때문 입니다.
사전의 키는 고유합니다. 따라서 정렬 된 사전에서 값을 무시하면 (예 : 값을 할당하여 None
) 본질적으로 정렬 된 세트를 갖습니다.
파이썬 3.1으로 있다 collections.OrderedDict
. 다음은 OrderedSet의 구현 예입니다. (단 몇 가지 방법을 정의 또는 오버라이드 (override) 할 필요가 있습니다 : collections.OrderedDict
와 collections.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__
OrderedSet
있는 서브 클래스 OrderedDict
와 abc.Set
다음, 정의 __len__
, __iter__
그리고 __contains__
.
collections
OrderedSet([1,2,3])
TypeError가 발생합니다. 생성자는 어떻게 작동합니까? 사용 예가 없습니다.
대답은 아니오이지만 동일한 목적 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']
dict.fromkeys()
있습니다. 그러나이 경우 키 순서는 CPython 3.6+ 구현에서만 유지되므로 OrderedDict
순서가 중요 할 때보다 이식 가능한 솔루션입니다.
keys = (1,2,3,1,2,1)
list(OrderedDict.fromkeys(keys).keys())
> [1, 2, 3]
, python-3.7. 효과가있다.
dict
, set
파이썬 3.7+ 불행하게도 순서를 유지하지 않습니다.
나는 당신에게 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 에서 무엇을 찾을 수 있는지에 대한 답변이 누락되었다고 생각합니다 .
패키지가 있습니다 :
이러한 구현 중 일부는 Raymond Hettinger가 ActiveState에 게시 한 레시피를 기반으로하며 여기에 다른 답변에서도 언급되어 있습니다.
my_set[5]
)remove(item)
모두 구현은 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 데이터 유형이 있습니다.
SortedSet
클래스 비교 및 해쉬로 구성원이 필요합니다.
set
하고 frozenset
또한 해쉬 될 요소가 필요합니다. 비교할 수있는 제약 조건은에 대한 추가 사항 SortedSet
이지만 명백한 제약 조건이기도합니다.
코드에서 이미 팬더를 사용중인 경우이 기사에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
indA.difference(indB)
합니다. 빼기 기호는 표준 빼기를 수행합니다
후반 게임에 조금씩, 그러나 나는 클래스를 작성했습니다 setlist
의 일환으로 collections-extended
이 완벽하게 구현 모두 Sequence
와Set
>>> from collections_extended import setlist
>>> sl = setlist('abracadabra')
>>> sl
setlist(('a', 'b', 'r', 'c', 'd'))
>>> sl[3]
'c'
>>> sl[-1]
'd'
>>> 'r' in sl # testing for inclusion is fast
True
>>> sl.index('d') # so is finding the index of an element
4
>>> sl.insert(1, 'd') # inserting an element already in raises a ValueError
ValueError
>>> sl.index('d')
4
GitHub : https://github.com/mlenzen/collections-extended
OrderedSet
공식 도서관 에는 없습니다 . 나는 당신의 참고를 위해 모든 데이터 구조의 철저한 치트 시트를 만듭니다.
DataStructure = {
'Collections': {
'Map': [
('dict', 'OrderDict', 'defaultdict'),
('chainmap', 'types.MappingProxyType')
],
'Set': [('set', 'frozenset'), {'multiset': 'collection.Counter'}]
},
'Sequence': {
'Basic': ['list', 'tuple', 'iterator']
},
'Algorithm': {
'Priority': ['heapq', 'queue.PriorityQueue'],
'Queue': ['queue.Queue', 'multiprocessing.Queue'],
'Stack': ['collection.deque', 'queue.LifeQueue']
},
'text_sequence': ['str', 'byte', 'bytearray']
}
ParallelRegression의 패키지는 제공 연주곡 ()를 더 메소드 완료 ActiveState의 조리법에 따라 옵션보다 세트 클래스를 명령했다. 리스트에 사용 가능한 모든 메소드를 지원하며, 모든 메소드가 세트에 사용 가능한 것은 아닙니다.
다른 답변에서 언급했듯이 python 3.7 이상에서는 dict이 정의에 따라 정렬됩니다. 서브 클래 싱 대신 서브 클래스 OrderedDict
를 만들 abc.collections.MutableSet
거나 typing.MutableSet
dict의 키를 사용하여 값을 저장할 수 있습니다.
class OrderedSet(typing.MutableSet[T]):
"""A set that preserves insertion order by internally using a dict."""
def __init__(self, iterable: t.Iterator[T]):
self._d = dict.fromkeys(iterable)
def add(self, x: T) -> None:
self._d[x] = None
def discard(self, x: T) -> None:
self._d.pop(x)
def __contains__(self, x: object) -> bool:
return self._d.__contains__(x)
def __len__(self) -> int:
return self._d.__len__()
def __iter__(self) -> t.Iterator[T]:
return self._d.__iter__()
그런 다음 :
x = OrderedSet([1, 2, -1, "bar"])
x.add(0)
assert list(x) == [1, 2, -1, "bar", 0]
이 코드를 작은 라이브러리에 넣었 으므로 누구나 사용할 수 있습니다 pip install
.
많은 목적을 위해 단순히 소트를 부르는 것으로 충분합니다. 예를 들어
>>> s = set([0, 1, 2, 99, 4, 40, 3, 20, 24, 100, 60])
>>> sorted(s)
[0, 1, 2, 3, 4, 20, 24, 40, 60, 99, 100]
이것을 반복해서 사용하려는 경우 정렬 된 함수를 호출하면 오버 헤드가 발생하므로 세트 변경을 완료 한 경우 결과 목록을 저장할 수 있습니다. 고유 한 요소를 유지 관리하고 정렬 해야하는 경우 None과 같은 임의의 값을 가진 컬렉션에서 OrderedDict를 사용하라는 제안에 동의합니다.
그래서 나는 또한 고유하지 않은 값을 도입 할 가능성이있는 작은 목록을 가지고있었습니다.
나는 일종의 고유 한 목록이 있는지 검색했지만 요소를 추가하기 전에 요소의 존재를 테스트하면 잘 작동한다는 것을 깨달았습니다.
if(not new_element in my_list):
my_list.append(new_element)
이 간단한 접근 방식에주의 사항이 있는지 모르겠지만 문제를 해결합니다.