programing

병렬 리스트의 해당 값에 따라 리스트 정렬

yellowcard 2023. 4. 10. 21:32
반응형

병렬 리스트의 해당 값에 따라 리스트 정렬

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

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"]

같은 「키」를 가지는 요소의 순서는 문제가 되지 않습니다.는 는는 i i i i i i i i i i i i i 。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. zip 두 사람lists.
  2. 정렬된 " " " 를 만듭니다.list에에에 zip를 사용합니다.
  3. 목록 이해를 사용하여 정렬되고 압축된 각 쌍의 첫 번째 요소를 추출합니다.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/에서 찾았습니다.

은 '아, 아, 아, 아,keyarg.

>>> 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)

원민무와 잭 펑이 지적한 바와 같이, 이것은 그 가치들이 다음과 같이 가정한다.X모두 구별됩니다.인덱스 목록을 사용하여 쉽게 관리할 수 있습니다.

>>> Z = ["A", "A", "C", "C", "C", "F", "G", "H", "I"]
>>> Z_index = list(range(len(Z)))
>>> Z_index.sort(key=keydict.get)
>>> Z = [Z[i] for i in Z_index]
>>> Z
['A', 'C', 'H', 'A', 'C', 'C', 'I', 'F', 'G']

Whatang이 설명한 데코레이션-소트-언데코레이션 접근법은 조금 더 간단하고 모든 경우에 적용되기 때문에 대부분의 경우 더 나을 수 있습니다.(이것은 매우 오래된 대답입니다!)

more_itertools 에는 반복가능성을 병렬로 정렬하는 도구가 있습니다.

정해진

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')

저는 실제로 값이 일치하는 목록별로 목록을 정렬하기 위해 여기에 왔습니다.

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

또 다른 대안으로, 몇 가지 답을 조합할 수 있습니다.

zip(*sorted(zip(Y,X)))[1]

python3에서 작업하려면:

list(zip(*sorted(zip(B,A))))[1]

나는 정렬된 색인 목록이 있는 것을 좋아한다.그러면 소스 목록과 같은 순서로 목록을 정렬할 수 있습니다.정렬된 인덱스 목록이 있으면 간단한 목록 이해로 다음과 같은 작업을 수행할 수 있습니다.

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"]

는 또한 렬음음음음음음음음음음음음음음음음음음음음 note note note note note note를 사용하여 얻을 .numpy.argsort().

zip, 두 번째 열로 정렬하고 첫 번째 열을 반환합니다.

zip(*sorted(zip(X,Y), key=operator.itemgetter(1)))[0]

이지만, 가 본 중 몇는 실제로 zip스크립팅할 수 없습니다. 치 않았다import operator및 이 모듈 및 이점에 대한 자세한 내용은 여기를 참조하십시오.

이 문제에 대해 적어도 두 가지 좋은 관용구가 있습니다.입력한 예부터 시작합니다.

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

"Decorate-Sort-Undecorate" 관용어 사용

이것은 R의 이름을 따서 Schwartzian_transform이라고도 합니다. 90년대에 Perl에서 이 패턴을 보급한 Schwartz:

# Zip (decorate), sort and unzip (undecorate).
# Converting to list to script the output and extract X
list(zip(*(sorted(zip(Y,X)))))[1]                                                                                                                       
# Results in: ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')

, 「」는 다음과 .Y ★★★★★★★★★★★★★★★★★」X이치노 첫 항목(「」, 「」의 항목(「」로부터)Y 두 항목: 두 번째 항목)입니다(출처)X)을 비교하는 등의 작업을 실시합니다.이렇게 하면 중복된 내용을 원래 순서로 유지하기 위해 사전 정렬 순서에 대한 원래 목록 인덱스를 포함하지 않는 한 출력이 불안정해질 수 있습니다.

모듈 사용

이것에 의해, 입력의 정렬 방법을 보다 직접적으로 제어할 수 있기 때문에, 소트 기준의 특정의 키를 말하는 것만으로, 소트 안정성을 얻을 수 있습니다.자세한 는 이쪽을 참조해 주세요.

import operator    

# Sort by Y (1) and extract X [0]
list(zip(*sorted(zip(X,Y), key=operator.itemgetter(1))))[0]                                                                                                 
# Results in: ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')

만들 수 요.pandas Series를 「」로서 data는 '''로 되어 있습니다.index이치노

import pandas as pd
pd.Series(data=X,index=Y).sort_index().tolist()

출력:

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

퀵 원라이너

list_a = [5,4,3,2,1]
list_b = [1,1.5,1.75,2,3,3.5,3.75,4,5]

리스트 a와 리스트 b를 일치시키고 싶다고 합니다.

orderedList =  sorted(list_a, key=lambda x: list_b.index(x))

이것은 작은 목록을 큰 값으로 주문해야 할 때 유용합니다.큰 목록이 작은 목록의 모든 값을 포함한다고 가정하면 이 작업을 수행할 수 있습니다.

정렬된 목록(python3)을 모두 가져오고 싶은 경우 Whatangs는 다음과 같이 답변합니다.

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

Zx, Zy = zip(*[(x, y) for x, y in sorted(zip(Y, X))])

print(list(Zx))  # [0, 0, 0, 1, 1, 1, 1, 2, 2]
print(list(Zy))  # ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

Zx와 Zy는 튜플이라는 것만 기억하세요.더 좋은 방법이 없을까 망설이고 있어요.

경고:빈 목록을 사용하여 실행하면 크래시됩니다.

저는 @Whatang의 답변에서 영감을 얻어 다른 목록을 기준으로 두 개 이상의 목록을 정렬하는 보다 일반적인 기능을 만들었습니다.

def parallel_sort(*lists):
    """
    Sorts the given lists, based on the first one.
    :param lists: lists to be sorted

    :return: a tuple containing the sorted lists
    """

    # Create the initially empty lists to later store the sorted items
    sorted_lists = tuple([] for _ in range(len(lists)))

    # Unpack the lists, sort them, zip them and iterate over them
    for t in sorted(zip(*lists)):
        # list items are now sorted based on the first list
        for i, item in enumerate(t):    # for each item...
            sorted_lists[i].append(item)  # ...store it in the appropriate list

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

이 작업은 한 줄로 수행할 수 있습니다.

X, Y = zip(*sorted(zip(Y, X)))

이 기능은 어레이에 대해 동작합니다.

def sortBoth(x,y,reverse=False):
    '''
    Sort both x and y, according to x. 
    '''
    xy_sorted=array(sorted(zip(x,y),reverse=reverse)).T
    return xy_sorted[0],xy_sorted[1]

위의 두 가지 리스트의 사이즈가 다르거나 아이템이 다르면 대부분의 솔루션이 작동하지 않을 것입니다.다음 솔루션은 단순하며 이러한 문제를 해결할 수 있습니다.

import pandas as pd

list1 = ['B', 'A', 'C']  # Required sort order
list2 = ['C', 'A']       # Items to be sorted according to list1

result = pd.merge(pd.DataFrame(list1), pd.DataFrame(list2))
print(list(result[0]))

출력:

['A', 'C']
  • 주의: list1에 없는 항목은 알고리즘이 사용하는 정렬 순서를 알 수 없으므로 무시됩니다.
list1 = ['a','b','c','d','e','f','g','h','i']
list2 = [0,1,1,0,1,2,2,0,1]

output=[]
cur_loclist = []

고유한 값을 가져오려면list2

list_set = set(list2)

에서 인덱스 위치를 찾으려면list2

list_str = ''.join(str(s) for s in list2)

의 인덱스 위치list2를 사용하여 추적합니다.cur_loclist

[0, 3, 7, 1, 2, 4, 8, 5, 6]

for i in list_set:
cur_loc = list_str.find(str(i))

while cur_loc >= 0:
    cur_loclist.append(cur_loc)
    cur_loc = list_str.find(str(i),cur_loc+1)

print(cur_loclist)

for i in range(0,len(cur_loclist)):
output.append(list1[cur_loclist[i]])
print(output)

위의 해결방법은 대부분 복잡하기 때문에 리스트의 길이가 다르거나 동일한 항목이 포함되지 않으면 효과가 없을 것입니다.아래 솔루션은 단순하며 Import가 필요하지 않습니다.

list1 = ['B', 'A', 'C']  # Required sort order
list2 = ['C', 'B']       # Items to be sorted according to list1

result = list1
for item in list1:
    if item not in list2: result.remove(item)

print(result)

출력:

['B', 'C']
  • 주의: list1에 없는 항목은 알고리즘이 사용하는 정렬 순서를 알 수 없으므로 무시됩니다.

나는 원래 질문의 제목이 정확하지 않다고 생각한다.항목 수가 동일한 목록이 2개 있고 목록 1의 모든 항목이 목록 2와 동일한 순서로 관련되는 경우(예: a = 0, b = 1 등), 질문은 '다른 목록의 값을 기준으로 목록을 정렬하는 방법'이 아니라 '사전 정렬 방법'이어야 합니다.이 경우 다음 솔루션이 가장 효율적입니다.

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

dict1 = dict(zip(X,Y))
result = sorted(dict1, key=dict1.get)
print(result)

결과:

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

언급URL : https://stackoverflow.com/questions/6618515/sorting-list-according-to-corresponding-values-from-a-parallel-list

반응형