Python – возвращает первый ключ N: пары значений из dict

Рассмотрим следующий словарь: d:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4} 

Я хочу вернуть первые пары ключей N: значение из d (N <= 4 в этом случае). Каков наиболее эффективный способ сделать это?

Нет такой вещи, как «первые n», потому что dict не помнит, какие ключи были вставлены в первую очередь.

Вы можете получить любые n пар ключ-значение, хотя:

 n_items = take(n, d.iteritems()) 

Это использует реализацию take из рецептов itertools :

 from itertools import islice def take(n, iterable): "Return first n items of the iterable as a list" return list(islice(iterable, n)) 

Смотрите, как работает онлайн: ideone

Очень эффективный способ получить что-либо – это комбинировать понимание списка или словаря с нарезкой. Если вам не нужно заказывать предметы (вам просто нужны n случайных пар), вы можете использовать понимание словаря следующим образом:

 first2pairs = {k: mydict[k] for k in mydict.keys()[:2]} 

Как правило, такое понимание всегда выполняется быстрее, чем эквивалентный цикл «for x in y». Кроме того, используя .keys (), чтобы составить список ключей словаря и нарезать этот список, вы избегаете «касания» любых ненужных ключей при создании нового словаря.

Если вам не нужны ключи (только значения), вы можете использовать понимание списка:

 first2vals = [v for v in mydict.values()[:2]] 

Если вам нужны значения, отсортированные по их ключам, это не намного больше проблем:

 first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]] 

или если вам нужны ключи:

 first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]} 

Питоны Питона не упорядочены, поэтому бессмысленно запрашивать «первые N» ключи.

Класс collections.OrderedDict доступен, если это то, что вам нужно. Вы могли бы эффективно получить первые четыре элемента в качестве

 import itertools import collections d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'))) x = itertools.islice(d.items(), 0, 4) for key, value in x: print key, value 

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

 x = list(itertools.islice(d.items(), 0, 4)) 

См. PEP 0265 о сортировке словарей. Затем используйте вышеупомянутый итерируемый код.

Если вам нужна большая эффективность в отсортированных парах ключ-значение. Используйте другую структуру данных. То есть тот, который поддерживает отсортированный порядок и ассоциации с ключом.

Например

 import bisect kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)] bisect.insort_left(kvlist, ('d', 4)) print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)] 

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

 n = 2 {key:value for key,value in d.items()[0:n]} 

Вы можете сделать это несколькими способами. Если порядок важен, вы можете сделать это:

 for key in sorted(d.keys()): item = d.pop(key) 

Если заказ не вызывает беспокойства, вы можете это сделать:

 for i in range(4): item = d.popitem() 

Это зависит от того, что «наиболее эффективно» в вашем случае.

Если вам просто нужен полуслучайный образец огромного словаря foo , используйте foo.iteritems() и возьмите столько значений из него, сколько вам нужно, это ленивая операция, которая позволяет избежать создания явного списка ключей или элементов.

Если вам нужно сначала отсортировать ключи, нет никакого способа использовать что-то вроде keys = foo.keys(); keys.sort() keys = foo.keys(); keys.sort() или sorted(foo.iterkeys()) , вам нужно будет создать явный список ключей. Затем нарезайте или пропустите первые N keys .

Кстати, почему вас волнует «эффективный» способ? Вы прокомментировали свою программу? Если вы этого не сделали, сначала используйте очевидный и понятный способ. Скорее всего, это будет очень хорошо, не став узким местом.

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

 import operator d = {'a': 3, 'b': 2, 'c': 3, 'd': 4} d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True)) #itemgetter(0)=sort by keys, itemgetter(1)=sort by values 

Теперь мы можем выполнить поиск верхних 'N' элементов :, используя структуру метода следующим образом:

 def return_top(elements,dictionary_element): '''Takes the dictionary and the 'N' elements needed in return ''' topers={} for h,i in enumerate(dictionary_element): if h<elements: topers.update({i:dictionary_element[i]}) return topers 

чтобы получить верхние 2 элемента, просто используйте эту структуру:

 d = {'a': 3, 'b': 2, 'c': 3, 'd': 4} d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True)) d=return_top(2,d) print(d) 
 foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6} iterator = iter(foo.items()) for i in range(3): print(next(iterator)) 

В принципе, поверните представление (dict_items) в итератор, а затем повторите его с помощью next ().