[python] 다른 목록의 값을 기준으로 목록을 정렬 하시겠습니까?

다음과 같은 문자열 목록이 있습니다.

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,   0,   1,   2,   2,   0,   1 ]

다음 출력을 얻기 위해 Y의 값을 사용하여 X를 정렬하는 가장 짧은 방법은 무엇입니까?

["a", "d", "h", "b", "c", "e", "i", "f", "g"]

동일한 “키”를 갖는 요소의 순서는 중요하지 않습니다. 나는 for구조 의 사용에 의지 할 수 있지만 더 짧은 방법이 있는지 궁금합니다. 어떤 제안?



답변

최단 코드

[x for _,x in sorted(zip(Y,X))]

예:

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

Z = [x for _,x in sorted(zip(Y,X))]
print(Z)  # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

일반적으로 말하면

[x for _, x in sorted(zip(Y,X), key=lambda pair: pair[0])]

설명 :

  1. ziplists.
  2. using list에 따라 새로운 정렬을 만듭니다 .zipsorted()
  3. 리스트 이해를 사용 하여 sorted, zipped에서 각 쌍의 첫 번째 요소를 추출 하십시오 list.

key파라미터와 sorted일반적인 기능 을 설정 / 사용하는 방법에 대한 자세한 내용 은 다음을 참조 하십시오 .



답변

두 목록을 압축하여 정렬 한 다음 원하는 부분을 가져갑니다.

>>> yx = zip(Y, X)
>>> yx
[(0, 'a'), (1, 'b'), (1, 'c'), (0, 'd'), (1, 'e'), (2, 'f'), (2, 'g'), (0, 'h'), (1, 'i')]
>>> yx.sort()
>>> yx
[(0, 'a'), (0, 'd'), (0, 'h'), (1, 'b'), (1, 'c'), (1, 'e'), (1, 'i'), (2, 'f'), (2, 'g')]
>>> x_sorted = [x for y, x in yx]
>>> x_sorted
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

이것을 결합하여 얻으십시오 :

[x for y, x in sorted(zip(Y, X))]


답변

또한 numpy 배열을 사용하지 않거나 실제로 이미 numpy 배열을 처리하는 중이라면 … 다른 좋은 해결책이 있습니다.

people = ['Jim', 'Pam', 'Micheal', 'Dwight']
ages = [27, 25, 4, 9]

import numpy
people = numpy.array(people)
ages = numpy.array(ages)
inds = ages.argsort()
sortedPeople = people[inds]

나는 그것을 여기에서 발견했다 :
http://scienceoss.com/sort-one-list-by-another-list/


답변

나에게 가장 확실한 해결책은 key키워드 arg 를 사용하는 것 입니다.

>>> X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
>>> Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]
>>> keydict = dict(zip(X, Y))
>>> X.sort(key=keydict.get)
>>> X
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

다음에 관심이 있다면 이것을 한 줄짜리로 줄이십시오.

>>> X.sort(key=dict(zip(X, Y)).get)


답변

실제로 값이 일치하는 목록을 기준으로 목록을 정렬하려고했습니다.

list_a = ['foo', 'bar', 'baz']
list_b = ['baz', 'bar', 'foo']
sorted(list_b, key=lambda x: list_a.index(x))
# ['foo', 'bar', 'baz']


답변

more_itertools iterable을 병렬로 정렬하는 도구가 있습니다.

주어진

from more_itertools import sort_together


X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

데모

sort_together([Y, X])[1]
# ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')


답변

나는 정렬 된 인덱스리스트를 좋아한다. 이렇게하면 소스 목록과 동일한 순서로 목록을 정렬 할 수 있습니다. 정렬 된 인덱스 목록이 있으면 간단한 목록 이해가 트릭을 수행합니다.

X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

sorted_y_idx_list = sorted(range(len(Y)),key=lambda x:Y[x])
Xs = [X[i] for i in sorted_y_idx_list ]

print( "Xs:", Xs )
# prints: Xs: ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

정렬 된 인덱스 목록은을 사용하여 얻을 수도 있습니다 numpy.argsort().