source

병렬 목록이 주어지면 다른 목록을 동일한 방식으로 순열(재배치)하면서 하나를 정렬하려면 어떻게 해야 합니까?

manycodes 2023. 4. 26. 23:28
반응형

병렬 목록이 주어지면 다른 목록을 동일한 방식으로 순열(재배치)하면서 하나를 정렬하려면 어떻게 해야 합니까?

내가 가지고 있다고 가정해보자면

list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

하기 르기list1.sort()정하여결로으과적렬로▁in▁will[1, 1, 2, 3, 4]하지만, 제가 받을 수 있을까요?list2그것과 동기화되어 재배치되는 것, 이런 결과를 얻는 것?

list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']

때때로 사람들은 문제를 다르게 표현합니다. 두 개의 목록이 주어지면 하나를 사용하여 다른 목록의 정렬 순서를 결정하려고 합니다. 즉, 정렬list2 값로 순대 로서설의 해당 값으로 list1비결은 이것이 "키" 값을 정렬하는 것과 같다는 것입니다.list1), 정렬합니다.list2같은방로으법 다시 되어 있는 입니다.다시 말해, 여기에 설명된 것과 정확히 일치합니다.그러나 다른 질문에 대한 일부 대답은 나중에 "정렬된 키"를 폐기합니다.

참고 항목:다른 목록에서 해당 구성요소가 나타나는 위치에 따라 목록을 정렬하려면 어떻게 해야 합니까? - 이것은 사용자가 한 목록을 다른 목록을 기준으로 정렬하려는 또 다른 일반적인 방법입니다.중복 질문을 닫기 전에 OP가 정확히 무엇을 원하는지 특별히 주의해야 합니다.핵심 단서: 목록의 길이가 같아야 합니까?

한 인 접근법은 ", 파이썬의 된 이에제인접근중 "decorate, sort, undecorate"를 하는 것입니다.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의 제안은 여전히 약간 빠르지만, Python은 모든 키 기반 정렬에 대해 내부적으로 동일한 DSU 관용구를 사용하기 때문에 아마도 조금 더 빠를 것입니다.그것은 단지 금속에 조금 더 가까운 곳에서 일어나고 있을 뿐입니다.(이것은 얼마나 잘 최적화되었는지를 보여줍니다.zip루틴은!)

제 생각엔zip기반 접근 방식이 더 유연하고 조금 더 읽기 쉬우므로 선호합니다.


참고로 다음의 요소가 있을 수 있습니다.list1경우, 이 동경한우방, 접은결다요국음비될다의 하게 될 입니다.list2 요소인경의 list2때 if if 비지원지않예때생부않습성니다지하을울교비를할: if: if).list2배열 하며, NumPy 배 목 록 열 며 것 이 요 들 이 소 만 약 할 이 패실의 실패합니다.list2비교하는 데 매우 비용이 많이 듭니다. 어쨌든 비교는 피하는 것이 더 나을 수 있습니다.

jfs의하거나, 의이jfs답제대정인나, 정요비를않의 키 할 수 .list2:

result1, result2 = zip(*sorted(zip(list1, list2), key=lambda x: x[0]))

한또, 의용의 .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')]

Python에서 쉽게 만들 수 있고 정렬할 수 있습니다.

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가장 빠른 것이 아닙니다. 사용하기가 더 쉽다는 것을 합니다.

이것은 Perl 프로그래머들이 decorate-sort-undecorate 관용구로도 알려진 Schwartzian 변환이라고 부르는 것을 사용하여 수행될 수 있습니다.내장된 Python 정렬은 안정적이므로 두 가지는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')]

당신은 할 수 .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']

이것이 도움이 되길 바랍니다.

한 가지 방법은 ID [0,1,2,...n]를 정렬하여 각 인덱스가 어디로 가는지 추적하는 것입니다.

이것은 임의의 수의 목록에 대해 작동합니다.

그런 다음 각 항목을 해당 위치로 이동합니다.스플라이스를 사용하는 것이 가장 좋습니다.

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

index = list(range(len(list1)))
print(index)
'[0, 1, 2, 3, 4]'

index.sort(key = list1.__getitem__)
print(index)
'[3, 4, 1, 0, 2]'

list1[:] = [list1[i] for i in index]
list2[:] = [list2[i] for i in index]

print(list1)
print(list2)
'[1, 1, 2, 3, 4]'
"['one', 'one2', 'two', 'three', 'four']"

목록을 정렬하지 않고도 반복할 수 있습니다.

list1_iter = (list1[i] for i in index)

다음은 어떻습니까?

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

이 numpy를 한다면, 은 numpy를 사용할 수 .np.argsort정렬된 인덱스를 가져와 해당 인덱스를 목록에 적용합니다.이 옵션은 정렬할 목록의 수에 관계없이 사용할 수 있습니다.

import numpy as np

arr1 = np.array([4,3,1,32,21])
arr2 = arr1 * 10
sorted_idxs = np.argsort(arr1)

print(sorted_idxs)
>>> array([2, 1, 0, 4, 3])

print(arr1[sorted_idxs])
>>> array([ 1,  3,  4, 21, 32])

print(arr2[sorted_idxs])
>>> array([ 10,  30,  40, 210, 320])

list2에 두 개의 동일한 값이 없는 한 sorted() 메서드에서 key 인수를 사용할 수 있습니다.

코드는 다음과 같습니다.

sorted(list2, key = lambda x: list1[list2.index(x)]) 

list.index() 함수는 list.index() 함수가 첫 번째 값을 제공하므로 list1의 해당 값에 따라 list2를 정렬하지만 이 값을 사용하는 동안 list2의 두 값이 동일하게 평가되지 않도록 합니다.

다른 목록을 기준으로 정렬할 때 문자열 목록의 순서를 유지하는 또 다른 방법은 다음과 같습니다.

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

# sort on list1 while retaining order of string list
sorted_list1 = [y for _,y in sorted(zip(list1,list2),key=lambda x: x[0])]
sorted_list2 = sorted(list1)

print(sorted_list1)
print(sorted_list2)

산출량

['one', 'one2', 'two', 'three', 'four']
[1, 1, 2, 3, 4]

두 개 이상의 목록을 동시에 정렬해야 할 경우 해결책을 제안하고자 합니다.

def SortAndSyncList_Multi(ListToSort, *ListsToSync):
    y = sorted(zip(ListToSort, zip(*ListsToSync)))
    w = [n for n in zip(*y)]
    return list(w[0]), tuple(list(a) for a in zip(*w[1]))

저는 제 문제에 큰 도움이 된 open jfs의 답변을 확장하고 싶습니다: 세 번째로 장식된 목록으로 두 개의 목록을 정렬합니다.

우리는 어떤 식으로든 장식된 목록을 만들 수 있지만, 이 경우에는 원래 목록 두 개 중 하나의 요소를 사용하여 정렬할 수 있습니다.

# say we have the following list and we want to sort both by the algorithms name 
# (if we were to sort by the string_list, it would sort by the numerical 
# value in the strings)
string_list = ["0.123 Algo. XYZ", "0.345 Algo. BCD", "0.987 Algo. ABC"]
dict_list = [{"dict_xyz": "XYZ"}, {"dict_bcd": "BCD"}, {"dict_abc": "ABC"}]

# thus we need to create the decorator list, which we can now use to sort
decorated = [text[6:] for text in string_list]  
# decorated list to sort
>>> decorated
['Algo. XYZ', 'Algo. BCD', 'Algo. ABC']

이제 JFS 솔루션을 적용하여 세 번째로 두 목록을 정렬할 수 있습니다.

# create and sort the list of indices
sorted_indices = list(range(len(string_list)))
sorted_indices.sort(key=decorated.__getitem__)

# map sorted indices to the two, original lists
sorted_stringList = list(map(string_list.__getitem__, sorted_indices))
sorted_dictList = list(map(dict_list.__getitem__, sorted_indices))

# output
>>> sorted_stringList
['0.987 Algo. ABC', '0.345 Algo. BCD', '0.123 Algo. XYZ']
>>> sorted_dictList
[{'dict_abc': 'ABC'}, {'dict_bcd': 'BCD'}, {'dict_xyz': 'XYZ'}]
newsource=[];newtarget=[]
for valueT in targetFiles:
    for valueS in sourceFiles:
            l1=len(valueS);l2=len(valueT);
            j=0
            while (j< l1):
                    if (str(valueT) == valueS[j:l1]) :
                            newsource.append(valueS)
                            newtarget.append(valueT)
                    j+=1

알고리즘 솔루션:

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']


lis = [(list1[i], list2[i]) for i in range(len(list1))]
list1.sort()
list2 = [x[1] for i in range(len(list1)) for x in lis if x[0] == i]

출력: -> 출력 속도: 0.2s

>>>list1
>>>[1, 1, 2, 3, 4]
>>>list2
>>>['one', 'one2', 'two', 'three', 'four']

방금 닫은 중복 질문에 대한 @pylang의 답변을 기반으로 인기 있는 타사 라이브러리에서 필요한 알고리즘을 구현합니다.more_itertools하나로

따라서:

from more_itertools import sort_together

list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

list1, list2 = sort_together(list1, list2)

python(십진수 값으로 정렬됨)에서 두 개의 ListParlerly 정렬

a = ['a','b','c','d','e','f']
b = ['0.23','80.00','5.01','6.58','1.38','79.06']
c=sorted(b,key=lambda x:float(x))
d=[]
for i in range(len(a)):
    d.append(a[b.index(c[i])])

언급URL : https://stackoverflow.com/questions/9764298/given-parallel-lists-how-can-i-sort-one-while-permuting-rearranging-the-other

반응형