두 가지 목록이 있다고 가정 해보십시오.
list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
내가 실행하면 list1.sort()
정렬 [1,1,2,3,4]
하지만 list2
동기화 하는 방법이 있습니까 (그래서 항목이에 4
속 한다고 말할 수 'three'
있습니까)? 따라서 예상되는 결과는 다음과 같습니다.
list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']
내 문제는 목록으로 잘 작동하는 꽤 복잡한 프로그램이 있지만 일부 데이터를 참조해야한다는 것입니다. 나는 이것이 사전에 대한 완벽한 상황이라는 것을 알고 있지만 키 값을 정렬해야하기 때문에 처리 과정에서 사전을 피하려고합니다 (사전을 사용해야하는 경우 사용 방법을 알고 있습니다).
기본적 으로이 프로그램의 본질은 데이터가 임의의 순서로 (위와 같이) 나옵니다. 데이터를 정렬하고 처리 한 다음 결과를 보내야합니다 (순서는 중요하지 않지만 사용자는 어떤 결과가 키). 먼저 사전에 넣은 다음 목록 하나를 정렬하는 방법에 대해 생각했지만 순서가 유지되지 않으면 동일한 값으로 항목을 구분하는 방법이 없습니다 (결과를 사용자에게 전달할 때 영향을 줄 수 있음). 이상적으로는 일단 목록을 얻으면 두 목록을 함께 정렬하는 방법을 찾는 것이 좋습니다. 이게 가능해?
답변
이 문제에 대한 한 가지 고전적인 접근 방식은 “장식, 정렬, 장식 해제”관용구를 사용하는 것입니다. 이는 파이썬의 내장 zip
함수를 사용하여 특히 간단 합니다.
>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2
('one', 'one2', 'two', 'three', 'four')
물론 이것들은 더 이상 목록이 아니지만 중요하다면 쉽게 해결됩니다.
>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']
위의 내용은 간결함을 위해 속도를 희생 할 수 있습니다. 3 줄을 차지하는 전체 버전은 내 컴퓨터에서 작은 목록에 비해 약간 빠릅니다.
>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop
반면에 더 큰 목록의 경우 한 줄 버전이 더 빠를 수 있습니다.
>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop
Quantum7이 지적했듯이 JSF의 제안 은 여전히 더 빠르지 만 파이썬은 모든 키 기반 정렬에 대해 내부적으로 동일한 DSU 관용구를 사용하기 때문에 조금 더 빠를 것 입니다. 베어 메탈에 조금 더 가깝습니다. (이것은 zip
루틴이 얼마나 최적화되었는지 보여줍니다 !)
나는 zip
기반 접근 방식이 더 유연하고 약간 더 읽기 쉽다고 생각 하므로 선호합니다.
답변
값을 키로 사용하여 색인을 정렬 할 수 있습니다.
indexes = range(len(list1))
indexes.sort(key=list1.__getitem__)
정렬 된 색인이 제공된 정렬 된 목록을 얻으려면 다음을 수행하십시오.
sorted_list1 = map(list1.__getitem__, indexes)
sorted_list2 = map(list2.__getitem__, indexes)
귀하의 경우에는 list1
, list2
대신 단일 쌍의 목록 이 있어야합니다 .
data = [(3, 'three'), (2, 'two'), (4, 'four'), (1, 'one'), (1, 'one2')]
작성하기 쉽습니다. 파이썬으로 정렬하는 것은 쉽습니다.
data.sort() # sort using a pair as a key
첫 번째 값으로 만 정렬하십시오.
data.sort(key=lambda pair: pair[0])
답변
나는 센더 레가 보낸 답을 오랫동안 발견했다 np.argsort
. 작동 방식은 다음과 같습니다.
# idx works on np.array and not lists.
list1 = np.array([3,2,4,1])
list2 = np.array(["three","two","four","one"])
idx = np.argsort(list1)
list1 = np.array(list1)[idx]
list2 = np.array(list2)[idx]
이 솔루션 이보다 직관적이며 실제로 잘 작동합니다. 성능 :
def sorting(l1, l2):
# l1 and l2 has to be numpy arrays
idx = np.argsort(l1)
return l1[idx], l2[idx]
# list1 and list2 are np.arrays here...
%timeit sorting(list1, list2)
100000 loops, best of 3: 3.53 us per loop
# This works best when the lists are NOT np.array
%timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 2.41 us per loop
# 0.01us better for np.array (I think this is negligible)
%timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best for 3 loops: 1.96 us per loop
비록 np.argsort
되지 가장 빠른 내가 사용하기 쉽게 찾을 수있다.
답변
슈바르츠 식 변환 . 내장 파이썬 정렬은 안정적이므로 두 가지로 1
인해 문제가 발생하지 않습니다.
>>> l1 = [3, 2, 4, 1, 1]
>>> l2 = ['three', 'two', 'four', 'one', 'second one']
>>> zip(*sorted(zip(l1, l2)))
[(1, 1, 2, 3, 4), ('one', 'second one', 'two', 'three', 'four')]
답변
이건 어떤가요:
list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']
sortedRes = sorted(zip(list1, list2), key=lambda x: x[0]) # use 0 or 1 depending on what you want to sort
>>> [(1, 'one'), (1, 'one2'), (2, 'two'), (3, 'three'), (4, 'four')]
답변
zip()
및 sort()
기능을 사용하여 이를 수행 할 수 있습니다 .
Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1] on cygwin
>>> list1 = [3,2,4,1,1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> zipped = zip(list1, list2)
>>> zipped.sort()
>>> slist1 = [i for (i, s) in zipped]
>>> slist1
[1, 1, 2, 3, 4]
>>> slist2 = [s for (i, s) in zipped]
>>> slist2
['one', 'one2', 'two', 'three', 'four']
도움이 되었기를 바랍니다
답변
list2에 두 개의 동일한 값이 없으면 sorted () 메소드에서 키 인수를 사용할 수 있습니다.
코드는 다음과 같습니다.
sorted(list2, key = lambda x: list1[list2.index(x)])
list1의 해당 값에 따라 list2를 정렬하지만 list.index () 함수가 첫 번째 값을 제공하므로 list2의 두 값이 같은 것으로 평가되지 않아야합니다.