2013-03-25 2 views
3

저는 여기에 파이썬 초보자입니다. 나는 아주 간단한 문제에 시달렸습니다. 그리고 이것을 해결하는 가장 효율적인 방법을 찾고 있습니다. 위의 목록 모두 (내 경우에는 500)와 동일한 크기가하나의 목록 정렬을 기반으로 파이썬에서 여러 목록 정렬

a,b,c,d,score 

을 다음과 같이 그래서, (5 개) 목록을 가지고있다. a,b,c,d은 문자열 목록이고 scoreint 목록입니다.

내가하고자하는 것은 score의 오름차순 또는 내림차순 정렬을 기준으로 a,b,c,d입니다. 따라서 우선 내림차순 패턴을 기반으로 score을 정렬 한 다음 정렬 된 점수 목록 (동일한 순서로)을 기준으로 a,b,c,d의 해당 요소를 정렬합니다.

내가 이것을 달성하기 위해 enumerate을 생각하고 있었지만, itertools을 사용하면 더 빠르고 효율적으로 사용할 수 있을지 궁금합니다.

달성 방법에 대한 안내는 & & 101 개 질문 인 경우 죄송합니다.

+1

제발, 비슷한 질문을 참조하십시오 : http : // stackoverflow.com/questions/6618515/sorting-list-based-from-another-list – alecxe

+0

이 차례로 http://stackoverflow.com/q/9543211/989121에 속합니다. 그러나 목록이 크고 파이썬 == 2이면 'it.izip'이 단지'zip'보다 낫습니다. – georg

답변

7
sorted_lists = sorted(izip(a, b, c, d, score), reverse=True, key=lambda x: x[4]) 
a, b, c, d, score = [[x[i] for x in sorted_lists] for i in range(5)] 

이 첫 번째 단계에서는 zip 목록을 함께 사용합니다. 이 함수는 모든 목록의 첫 번째 요소를 가져 와서 튜플에 넣고 해당 튜플을 새 목록에 추가 한 다음 모든 목록의 두 번째 요소에 대해 동일한 작업을 반복합니다. 그런 다음 다섯 번째 요소로이 튜플 목록을 정렬합니다 (이 매개 변수는 key 인수에 전달 된 익명 함수에서 가져온 것입니다). 목록이 내림차순이되도록 reverse=True을 설정합니다.

두 번째 단계에서는 일부 중첩 된 목록 보급 및 튜플 압축 풀기를 사용하여 목록을 분리합니다. 우리는 목록의 새로운 목록을 만듭니다. 각 내부 목록은 각 터플의 첫 번째 요소입니다 (sorted_lists). 아래로 한 줄에서이 작업을 수행 할 수 있지만 두 조각으로 분할하는 것은 조금 더 명확한 것 같아요 : 여기

a, b, c, d, score = izip(*sorted(izip(a, b, c, d, score), reverse=True, 
         key=lambda x: x[4])) 

는 튜플이 분류 목록은 튜플의 목록을 반환하는 일반적인 기능입니다 :

는 숫자 일 또는 배열 조작을 많이 수행하는 경우
def sort_lists_by(lists, key_list=0, desc=False): 
    return izip(*sorted(izip(*lists), reverse=desc, 
       key=lambda x: x[key_list])) 
+0

당신의 멋진 솔루션에 대한 EML에 감사드립니다 - 저는 궁금 해서요 - x [4]와'range (5) '가 피할 수있는 더 일반적인 해결책이있을 수 있습니까? 나는 5 개 이상의 목록을 가질 수 있기 때문에이 질문을하고 있는데, 값이 하드 코드 된 시점을 이해하는 데 도움이되는지 확신 할 수 없다. ( – AJW

+0

일반 함수를 추가하기 위해 편집 됨. 'range (5)'는 서브리스트에있는 각 요소의 인덱스를 반환하므로 각 서브리스트를 압축 한 후에 다시 열 수 있습니다 .x [4]는 다른 모든리스트를 정렬하는 목록을 나타 내기위한 것입니다. – EML

+0

재미있는 'zip'은 중첩 된 목록을 중첩합니다. 배열을 바꾸는 것과 유사한 기능 – Eike

2

, 그것은 numpy을 사용으로 찾고 가치가있을 수도 있습니다. 이에서

In [1]: import numpy as np 
In [2]: a = ['hi','hello'] 
In [3]: b = ['alice','bob'] 
In [4]: c = ['foo','bar'] 
In [5]: d = ['spam','eggs'] 
In [6]: score = [42,17] 

는, 형식 (a,b,c,d,score)에서 튜플의 목록을 작성하고 DTYPE (str,str,str,str,int) 각 하나를 저장하고, 당신도 그들에 액세스 할 수 이름을 그들에게 ('a','b','c','d','score')을 제공 할 수 있습니다 :이 문제는 매우 쉽게 NumPy와 배열로 해결 나중에 :

In [7]: data = np.array(zip(a,b,c,d,score), 
    ...:   dtype = [('a','S5'),('b','S5'),('c','S5'),('d','S5'),('score',int)] 
    ...: ) 

In [8]: data 
Out[8]: 
array([('hi', 'alice', 'foo', 'spam', 42), 
     ('hello', 'bob', 'bar', 'eggs', 17)], 
     dtype=[('a', 'S5'), ('b', 'S5'), ('c', 'S5'), ('d', 'S5'), ('score', '<i8')]) 

이 배열의 장점은 자신의 이름으로 모든 '목록'(필드)에 액세스 할 수 있습니다 :

In [9]: data['a'] 
Out[9]: 
array(['hi', 'hello'], 
     dtype='|S5') 

In [10]: data['score'] 
Out[10]: array([42, 17]) 

정렬하려면 다음과 같이 정렬 할 필드 이름을 지정하십시오.

In [11]: sdata = np.sort(data, order='score') 

In [12]: sdata 
Out[12]: 
array([('hello', 'bob', 'bar', 'eggs', 17), 
     ('hi', 'alice', 'foo', 'spam', 42)], 
     dtype=[('a', 'S5'), ('b', 'S5'), ('c', 'S5'), ('d', 'S5'), ('score', '<i8')]) 

In [13]: sdata['b'] 
Out[13]: 
array(['bob', 'alice'], 
     dtype='|S5')