최근에 나는 내가 변환하고 때 눈치 list
로 set
요소의 순서를 변경하고 문자로 정렬됩니다.
이 예를 고려하십시오.
x=[1,2,20,6,210]
print x
# [1, 2, 20, 6, 210] # the order is same as initial order
set(x)
# set([1, 2, 20, 210, 6]) # in the set(x) output order is sorted
내 질문은-
- 왜 이런 일이 발생합니까?
- 초기 주문을 잃지 않고 설정 작업 (특히 차액 설정)을 수행하려면 어떻게해야합니까?
답변
-
A
set
는 정렬되지 않은 데이터 구조이므로 삽입 순서를 유지하지 않습니다. -
이것은 요구 사항에 따라 다릅니다. 일반 목록이 있고 목록의 순서를 유지하면서 일부 요소 집합을 제거하려는 경우 목록 이해를 사용하여이를 수행 할 수 있습니다.
>>> a = [1, 2, 20, 6, 210] >>> b = set([6, 20, 1]) >>> [x for x in a if x not in b] [2, 210]
빠른 멤버십 테스트 와 삽입 순서 보존을 모두 지원하는 데이터 구조가 필요한 경우 Python 3.7부터 삽입 순서를 유지하는 Python 사전의 키를 사용할 수 있습니다.
>>> a = dict.fromkeys([1, 2, 20, 6, 210]) >>> b = dict.fromkeys([6, 20, 1]) >>> dict.fromkeys(x for x in a if x not in b) {2: None, 210: None}
b
여기서 주문할 필요가 없습니다set
. a 도 사용할 수 있습니다 . 참고a.keys() - b.keys()
A와 차 집합을 반환set
이 삽입 순서를 유지하지 않도록.이전 버전의 Python에서는
collections.OrderedDict
대신 다음을 사용할 수 있습니다 .>>> a = collections.OrderedDict.fromkeys([1, 2, 20, 6, 210]) >>> b = collections.OrderedDict.fromkeys([6, 20, 1]) >>> collections.OrderedDict.fromkeys(x for x in a if x not in b) OrderedDict([(2, None), (210, None)])
답변
Python 3.6에서는 Python 2 및 3에 대한 또 다른 솔루션이 있습니다.set()
이제 순서를 유지 해야 하지만
>>> x = [1, 2, 20, 6, 210]
>>> sorted(set(x), key=x.index)
[1, 2, 20, 6, 210]
답변
첫 번째 질문에 대한 답으로 집합은 집합 작업에 최적화 된 데이터 구조입니다. 수학적 집합과 마찬가지로 요소의 특정 순서를 적용하거나 유지하지 않습니다. 집합의 추상 개념은 순서를 적용하지 않으므로 구현이 필요하지 않습니다. 목록에서 집합을 만들 때 Python은 집합 작업을 효율적으로 수행 할 수있는 집합에 대해 사용하는 내부 구현의 요구에 따라 요소의 순서를 자유롭게 변경할 수 있습니다.
답변
아래 기능으로 중복 제거 및 순서 유지
def unique(sequence):
seen = set()
return [x for x in sequence if not (x in seen or seen.add(x))]
답변
- set : 고유 요소의 정렬되지 않은 컨테이너 (구현 됨)
- oset : 고유 요소의 정렬 된 컨테이너 (NotImplemented)
Python에서는 세트 만 직접 구현됩니다. 일반 사전 키 ( 3.7+ )로 osets를 에뮬레이트 할 수 있습니다 .
주어진
a = [1, 2, 20, 6, 210, 2, 1]
b = {2, 6}
암호
oset = dict.fromkeys(a).keys()
# dict_keys([1, 2, 20, 6, 210])
데모
복제는 제거되고 삽입 순서는 유지됩니다.
list(oset)
# [1, 2, 20, 6, 210]
딕셔너리 키에 대한 세트와 유사한 작업.
oset - b
# {1, 20, 210}
oset | b
# {1, 2, 5, 6, 20, 210}
oset & b
# {2, 6}
oset ^ b
# {1, 5, 20, 210}
세부
참고 : 정렬되지 않은 구조는 정렬 된 요소를 배제하지 않습니다. 오히려 유지 된 순서는 보장되지 않습니다. 예:
assert {1, 2, 3} == {2, 3, 1} # sets (order is ignored)
assert [1, 2, 3] != [2, 3, 1] # lists (order is guaranteed)
목록 과 다중 집합 (mset)이 두 가지 더 매력적인 수학적 데이터 구조 라는 사실을 알게되면 기뻐할 수 있습니다 .
- list : 복제를 허용하는 정렬 된 요소 컨테이너 (구현 됨)
- mset : 복제를 허용하는 요소의 정렬되지 않은 컨테이너 (NotImplemented) *
요약
Container | Ordered | Unique | Implemented
----------|---------|--------|------------
set | n | y | y
oset | y | y | n
list | y | n | y
mset | n | n | n*
* 다중 집합은 collections.Counter()
딕셔너리와 유사한 다중도 (개수) 매핑을 사용하여 간접적으로 에뮬레이션 할 수 있습니다 .
답변
다른 답변에서 알 수 있듯이 세트는 요소 순서를 유지하지 않는 데이터 구조 (및 수학적 개념)입니다.
그러나 세트와 사전의 조합을 사용하면 원하는대로 얻을 수 있습니다. 다음 스 니펫을 사용해보세요.
# save the element order in a dict:
x_dict = dict(x,y for y, x in enumerate(my_list) )
x_set = set(my_list)
#perform desired set operations
...
#retrieve ordered list from the set:
new_list = [None] * len(new_set)
for element in new_set:
new_list[x_dict[element]] = element
답변
Sven의 답변을 바탕으로 collections.OrderedDict를 사용하여 원하는 것을 달성하고 dict에 더 많은 항목을 추가 할 수 있습니다.
import collections
x=[1,2,20,6,210]
z=collections.OrderedDict.fromkeys(x)
z
OrderedDict([(1, None), (2, None), (20, None), (6, None), (210, None)])
항목을 추가하고 싶지만 여전히 세트처럼 취급하려면 다음을 수행하십시오.
z['nextitem']=None
그리고 dict에서 z.keys ()와 같은 작업을 수행하고 세트를 가져올 수 있습니다.
z.keys()
[1, 2, 20, 6, 210]