У меня есть collections.defaultdict (интервал), который я создаю для проведения подсчета того, сколько раз ключ разоблачает в ряде данных. Я позже хочу быть в состоянии отсортировать его (очевидно, путем превращения его в список сначала) убывающим способом, заказанным с самыми высокими значениями сначала. Я создал свой словарь как следующее:
adict = defaultdict(int)
позже я делаю набор:
adict['someval'] += 1
adict['anotherval'] +=1
adict['someval'] += 1
Идеально после этого я хотел бы получить печать из:
someval => 2
anotherval => 1
Ключи dict, отсортированные в обратном порядке по соответствующим значениям, лучше всего получить как
sorted(adict, key=adict.get, reverse=True)
, поскольку вам нужны пары ключ / значение, вы можете работать с элементами, как предлагают все другие ответы, или (чтобы использовать изящный adict.get
связанный метод вместо itemgetters или странных лямбда-выражений; -),
[(k, adict[k]) for k in sorted(adict, key=adict.get, reverse=True)]
Edit : с точки зрения производительности в этом нет ничего особенного:
$ python -mtimeit -s'adict=dict((x,x**2) for x in range(-5,6))' '[(k, adict[k]) for k in sorted(adict, key=adict.get, reverse=True)]'
100000 loops, best of 3: 10.8 usec per loop
$ python -mtimeit -s'adict=dict((x,x**2) for x in range(-5,6)); from operator import itemgetter' 'sorted(adict.iteritems(), key=itemgetter(1), reverse=True)'
100000 loops, best of 3: 9.66 usec per loop
$ python -mtimeit -s'adict=dict((x,x**2) for x in range(-5,6))' 'sorted(adict.iteritems(), key=lambda (k,v): v, reverse=True)'
100000 loops, best of 3: 11.5 usec per loop
Итак, решение на основе .get
находится посередине по производительности между двумя items
-содержащими решениями - немного медленнее, чем itemgetter
, немного быстрее, чем лямбда
. В «узких» случаях, когда эти доли микросекунд важны для вас, обязательно сосредоточьтесь на этом. В обычных случаях
Чтобы отсортировать словарь:
from operator import itemgetter
sorted(adict.iteritems(), key=itemgetter(1), reverse=True)
Просто отсортируйте полученный дикт по значениям:
for k, v in sorted(adict.items(), key=lambda kv: kv[1], reverse=True):
print("%s => %s" % (k,v))
If you're using the newest python 2.7 alpha, then you can use the Counter
class in collections module:
c = Counter()
c['someval'] += 1
c['anotherval'] += 1
c['someval'] += 1
print c.most_common()
prints in the correct order:
[('someval', 2), ('anotherval', 1)]
The code used on 2.7 is available already and there's a version adapted to 2.5. Perhaps you want to use it to stay forward compatible with the native stdlib version that is about to be released.
from collections import defaultdict
adict = defaultdict(int)
adict['a'] += 1
adict['b'] += 3
adict['c'] += 5
adict['d'] += 2
for key, value in sorted(adict.items(), lambda a, b: cmp(a[1], b[1]), reverse=True):
print "%r => %r" % (key, value)
>>>
'c' => 5
'b' => 3
'd' => 2
'a' => 1
«Инвертировать» словарь.
from collections import defaultdict
inv_dict = defaultdict( list )
for key, value in adict:
inv_dict[value].append( key )
max_value= max( inv_dict.keys() )
Набор ключей с максимальным числом вхождений -
inv_dict[max_value]
Набор ключей в порядке убывания их появления -
for value, key_list in sorted( inv_dict ):
print key_list, value
Примечание: я помещаю это как ответ, чтобы его заметили. Я не хочу голосов. Если вы хотите проголосовать за кого-нибудь, проголосуйте за Надю.
, принятый в настоящее время ответ дает результаты по времени, которые основаны на тривиально небольшом наборе данных (size == 6 - (-5) == 11 ). Различия в стоимости различных методов маскируются накладными расходами. Такой вариант использования, как наиболее часто встречающиеся слова в тексте или наиболее частые имена в списке членства или переписи, включает гораздо большие наборы данных.
Повторение эксперимента с диапазоном (-n, n + 1) (Windows box, Python 2.6 .4, все время в микросекундах):
n = 5: 11,5, 9,34, 11,3
n = 50: 65,5, 46,2, 68,1
n = 500: 612, 423, 614
Эти результаты НЕ "немного" отличаются. Ответ itemgetter - явный победитель по скорости.
Также было упомянуто " простота получить
идиому ". Сложим их вместе для удобства сравнения:
[(k, adict [k]) для k в отсортированном (adict, key = adict.get, reverse = True)]
отсортированном (adict.iteritems (), key = itemgetter (1) , reverse = True)
Идиома get
не только просматривает словарь дважды (как указал Дж. Ф. Себастьян), но и составляет один список (результат sorted ()
) затем перебирает этот список, чтобы создать список результатов. Я бы назвал это барокко, а не простым . YMMV.