python 출력 - 파이썬 - 튜플 목록을 다른 목록으로 정렬




2 Answers

연산

두 번째 요소에 따라 목록의 dict에 튜플을 배포하고 정렬 된 인덱스를 반복하여 정렬 된 목록을 얻을 수 있습니다.

from collections import defaultdict
to_order = [(0, 1), (1, 3), (2, 2), (3, 2)]
order = [2, 1, 3]

bins = defaultdict(list)

for pair in to_order:
    bins[pair[1]].append(pair)

print(bins)
# defaultdict(<class 'list'>, {1: [(0, 1)], 3: [(1, 3)], 2: [(2, 2), (3, 2)]})

print([pair for i in order for pair in bins[i]])
# [(2, 2), (3, 2), (0, 1), (1, 3)]

sort 또는 index 이 필요하지 않으며 출력이 안정적입니다.

이 알고리즘은 가정 duplicate 언급 된 mapping 과 비슷합니다. 이 링크 된 답변은 to_orderorder 의 길이가 같은 경우에만 작동하며 OP의 질문에는 해당되지 않습니다.

공연

이 알고리즘은 to_order 각 요소를 두 번 반복합니다. 복잡성은 O(n) 입니다. @ alfasin의 첫 번째 알고리즘은 훨씬 느립니다 ( O(n * m * log n) ). 그러나 두 번째 알고리즘도 O(n) 입니다.

다음은 0 에서 1000 사이의 10000 개의 무작위 쌍을 가진 목록입니다. 고유 한 두 번째 요소를 추출하고 순서를 정의 order 순서를 섞습니다.

from random import randrange, shuffle
from collections import defaultdict
from timeit import timeit
from itertools import chain

N = 1000
to_order = [(randrange(N), randrange(N)) for _ in range(10*N)]
order = list(set(pair[1] for pair in to_order))
shuffle(order)


def eric(to_order, order):
    bins = defaultdict(list)
    for pair in to_order:
        bins[pair[1]].append(pair)
    return list(chain.from_iterable(bins[i] for i in order))


def alfasin1(to_order, order):
    arr = [[] for i in range(len(order))]
    d = {k:v for v, k in enumerate(order)}
    for item in to_order:
        arr[d[item[1]]].append(item) 
    return [item for sublist in arr for item in sublist]

def alfasin2(to_order, order):
    return sorted(to_order, key=lambda item: order.index(item[1]))

print(eric(to_order, order) == alfasin1(to_order, order))
# True
print(eric(to_order, order) == alfasin2(to_order, order))
# True

print("eric", timeit("eric(to_order, order)", globals=globals(), number=100))
# eric 0.3117517130003762
print("alfasin1", timeit("alfasin1(to_order, order)", globals=globals(), number=100))
# alfasin1 0.36100843100030033
print("alfasin2", timeit("alfasin2(to_order, order)", globals=globals(), number=100))
# alfasin2 15.031453827000405
':' 튜토리얼

나는 to_order 과 같은 튜플리스트를 가지고있다 :

to_order = [(0, 1), (1, 3), (2, 2), (3,2)]

to_order 의 각 튜플의 두 번째 요소에 적용 할 순서를 지정하는 목록은 다음과 to_order .

order = [2, 1, 3]

그래서 나는이 산출물을 얻는 방법을 찾고있다.

ordered_list = [(2, 2), (3,2), (0, 1), (1, 3)]

어떤 아이디어?




또 다른 해결책 : [item for key in order for item in filter(lambda x: x[1] == key, to_order)]

이 솔루션은 먼저 order 작동하며 각 key 에 대해 to_orderorder 필터링합니다.

동등한:

ordered = []
for key in order:
    for item in filter(lambda x: x[1] == key, to_order):
        ordered.append(item)

더 짧지 만 목록 이해력으로이 작업을 수행하는 방법을 알지 못합니다.

ordered = []
for key in order:
    ordered.extend(filter(lambda x: x[1] == key, to_order))

참고 : to_orderx[1]order 가 아닌 튜플 x 가 포함되어 있으면 ValueError 가 throw되지 않습니다.




Related