2015-12-03 6 views
0

У меня есть словарь:Сортировка словаря по значению (список) применение функции к нему

students = { 
    '1': [32, 14, 31, 23], 
    '2': [32, 8, 36.5, 22], 
    '3': [26, 11, 39, 15.5], 
    '4': [34, 15, 44, 25], 
    '5': [30, 6, 25, 24], 
    '6': [26, 8, 31, 13], 
    '7': [24, 4, 16, 17], 
    '8': [22, 2, 0, 11.2], 
    '9': [22, 4, 15, 10], 
    '10': [31, 4, 16, 4.2], 
    '11': [18, 3.5, 0, 0], 
    '12': [28, 5, 30, 18.5], 
    '13': [34, 13, 23, 13], 
} 

Я хочу, чтобы отсортировать словарь по сумме каждого списка. Так что я мог бы сделать это следующим образом:

import operator 

students = { 
    '1': sum([32, 14, 31, 23]), 
    '2': sum([32, 8, 36.5, 22]), 
    '3': sum([26, 11, 39, 15.5]), 
    '4': sum([34, 15, 44, 25]), 
    '5': sum([30, 6, 25, 24]), 
    '6': sum([26, 8, 31, 13]), 
    '7': sum([24, 4, 16, 17]), 
    '8': sum([22, 2, 0, 11.2]), 
    '9': sum([22, 4, 15, 10]), 
    '10': sum([31, 4, 16, 4.2]), 
    '11': sum([18, 3.5, 0, 0]), 
    '12': sum([28, 5, 30, 18.5]), 
    '13': sum([34, 13, 23, 13]), 
} 

sorted_students = sorted(
    students.items(), key=operator.itemgetter(1), reverse=True) 

Но:

  1. Я не хочу, чтобы изменить словарь, я хочу иметь списки в качестве значений
  2. Я не хочу писать sum() много раз.

key=sum(operator.itemgetter(1)) Я попытался, но ясно, что он не будет работать, я получаю:

TypeError: 'operator.itemgetter' object is not iterable 

Что является более эффективным способом, чтобы сделать то, что я хочу?

ответ

3

Они ключ должен быть calalble, так что вам нужно обернуть операцию в функции:

key = lambda x: sum(x[1]) 
4

словари не упорядочены, поэтому нельзя «сортировать словарь». Если вы хотите, однако, отдельный список ключей, которые заказали, это выполнимо:

>>> students = { 
    '1': [32, 14, 31, 23], 
    '2': [32, 8, 36.5, 22], 
    '3': [26, 11, 39, 15.5], 
    '4': [34, 15, 44, 25], 
    '5': [30, 6, 25, 24], 
    '6': [26, 8, 31, 13], 
    '7': [24, 4, 16, 17], 
    '8': [22, 2, 0, 11.2], 
    '9': [22, 4, 15, 10], 
    '10': [31, 4, 16, 4.2], 
    '11': [18, 3.5, 0, 0], 
    '12': [28, 5, 30, 18.5], 
    '13': [34, 13, 23, 13], 
} 
>>> sortedKeys = sorted(students.keys(), key = lambda x: sum(students[x])) 
>>> sortedKeys 
['11', '8', '9', '10', '7', '6', '12', '13', '5', '3', '2', '1', '4'] 

вы можете перебирать список, как вы итерацию по dict начиная с iter(dict) итерации через ключи dict в любом случае.

>>> for key in sortedKeys: 
    print(key,sum(students[key])) 


11 21.5 
8 35.2 
9 51 
10 55.2 
7 61 
6 78 
12 81.5 
13 83 
5 85 
3 91.5 
2 98.5 
1 100 
4 118 
1

Если вы хотите сделать заказ, основанный на самой высокой суммы использовать OrderedDict после сортировки по сумме:

from collections import OrderedDict 

students = OrderedDict(sorted(students.items(),key=lambda x: sum(x[1]))) 


OrderedDict([('11', [18, 3.5, 0, 0]), ('8', [22, 2, 0, 11.2]), 
      ('9', [22, 4, 15, 10]), ('10', [31, 4, 16, 4.2]), 
      ('7', [24, 4, 16, 17]), ('6', [26, 8, 31, 13]), 
      ('12', [28, 5, 30, 18.5]), ('13', [34, 13, 23, 13]), 
      ('5', [30, 6, 25, 24]), ('3', [26, 11, 39, 15.5]), 
      ('2', [32, 8, 36.5, 22]), ('1', [32, 14, 31, 23]), 
     ('4', [34, 15, 44, 25])]) 

Если вы хотите сортируется от самого высокого до самого низкого использования суммы -sum(... в sorted.

students = OrderedDict(sorted(students.items(),key=lambda x: -sum(x[1]))) 

print(students) 
OrderedDict([('4', [34, 15, 44, 25]), ('1', [32, 14, 31, 23]), 
     ('2', [32, 8, 36.5, 22]), ('3', [26, 11, 39, 15.5]), 
     ('5', [30, 6, 25, 24]), ('13', [34, 13, 23, 13]), 
     ('12', [28, 5, 30, 18.5]), ('6', [26, 8, 31, 13]), 
     ('7', [24, 4, 16, 17]), ('10', [31, 4, 16, 4.2]), 
     ('9', [22, 4, 15, 10]), ('8', [22, 2, 0, 11.2]), 
     ('11', [18, 3.5, 0, 0])]) 
1

Поскольку это не представляется возможным, чтобы отсортировать словарь, мы можем получить только представление Словаря, который сортируется, который будет список, на самом деле список кортежей.

d = {k: sum(i for i in v) for k,v in students.items()} 
print (sorted(d.items(), key=operator.itemgetter(1))) 

Выход:

[('11', 21.5), ('8', 35.2), ('9', 51), ('10', 55.2), ('7', 61), ('6', 78), ('12', 81.5), ('13', 83), ('5', 85), ('3', 91.5), ('2', 98.5), ('1', 100), ('4', 118)] 
Смежные вопросы