2016-10-14 2 views
1

Так я Dict как следующее:Python: сортировка списков словаря на основе показателей одного списка

dict1 = {1: [-1, 1, 2, 4, 3], 2: [11, 10, 9, 8, 7]} 

Как можно сортировать списки в dict1 на основе показателей, которые сортируют одно из списки. Такие, как отсортированные индексы списка

[11, 10, 9, 8, 7] 

который

[4, 3, 2, 1, 0] 

Таким образом, новый dict1 будет:

dict1 = {1: [3, 4, 2, 1, -1], 2: [7, 8, 9, 10, 11]} 

Я попытался следующий код:

sorted(dict1.items(), key=lambda t: t[1]) 

Но все еще не может f настроить его? Я могу использовать цикл for для выполнения этой работы, но я считаю, что существует более пифонический путь. Есть идеи?

+4

Как вы имеете в виду * на основе индексов, которые будут сортировать один из списков *? –

+2

'[3, 4, 2, 1, -1]' не сортируется –

+0

Вы ищете 'dict1 [2] .sort()'? – Akavall

ответ

4

Одним из способов было бы вычислить список индексов и применить его ко всем спискам:

>>> dict1 = {1: [-1, 1, 2, 4, 3], 2: [11, 10, 9, 8, 7]} 
>>> basis = dict1[2] 
>>> indexes = sorted(range(len(basis)), key=basis.__getitem__) 
>>> for lst in dict1.values(): 
     lst[:] = [lst[i] for i in indexes] 

>>> dict1 
{1: [3, 4, 2, 1, -1], 2: [7, 8, 9, 10, 11]} 

Если вы нормально с «первым» список, определяющий порядок (вы только сказали «на основе [ ...] один из списков»), можно также построить столбцы и сортировки тем:

>>> dict1 = {1: [-1, 1, 2, 4, 3], 2: [11, 10, 9, 8, 7]} 
>>> dict(zip(dict1.keys(), zip(*sorted(zip(*dict1.values()))))) 
{1: (-1, 1, 2, 3, 4), 2: (11, 10, 9, 7, 8)} 
+0

Да. Оно работает. Однако индексы могут исходить из любого из списков в dict. Хотя я мог бы избежать использования цикла 'for' для сортировки. Но я не знал способ обновления dict, который я использовал здесь. Довольно умный. Спасибо за Ваш ответ. –

+0

dicts iserable –

+0

@PadraicCunningham Я знаю. Но почему ты так говоришь? –

1

Сортировка с помощью перечисления, чтобы получить отсортированные индексы и просто использовать индексы для сортировки других списков:

from operator import itemgetter 
dict1 = {1: [-1, 1, 2, 4, 3], 2: [11, 10, 9, 8, 7]} 

l = [i for i, _ in sorted(enumerate(dict1[2]), key=itemgetter(1))] 


for v in dict1.values(): 
    v[:] = (v[i] for i in l) 
print(dict1) 

Или, если вы хотите новый Dict:

l = [i for i, _ in sorted(enumerate(dict1[2]), key=itemgetter(1))] 
new = {k: [v[i] for i in l] for k, v in dict1.items()} 

Или, если вы не возражаете кортежи:

new = {k: itemgetter(*l)(v) for k, v in dict1.items()}) 
+0

Я думаю, что лучший способ получить отсортированные индексы - это: 'indices = np.argsort (dict1 [2])' –

+0

@JianliCheng, поэтому я спросил, как вы его используете, используете ли вы массивы или списки numpy? –

+1

@ Padraic Cunningham, до тех пор, пока списки в dict могут быть обновлены. Причина, по которой я использую numpy для получения отсортированных индексов, - это просто потому, что это более просто. Но я не знал о itemgetter, спасибо, что дал мне знать. –

0

Использование itemgetter в dictionary comprehension

>>> from operator import itemgetter 
>>> order = [4, 3, 2, 1, 0] 
>>> key = itemgetter(*order) 
>>> {k: key(dict1[k]) for k in dict1} 
{1: (3, 4, 2, 1, -1), 2: (7, 8, 9, 10, 11)} 
+0

Хотя этот фрагмент кода может решить вопрос, [включая объяснение] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. – andreas

+0

@ Andreas Я предоставил ссылки на соответствующую документацию, которые объясняют это очень хорошо. Сам код очень понятен, поэтому официальной документации будет достаточно. – jamylak

Смежные вопросы