Рассмотрим следующий словарь, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Я хочу вернуть первые N пар ключ: значение из d (в данном случае N <= 4). Какой метод для этого наиболее эффективен?
Рассмотрим следующий словарь, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Я хочу вернуть первые N пар ключ: значение из d (в данном случае N <= 4). Какой метод для этого наиболее эффективен?
Ответы:
Не существует такой вещи, как "первые n" ключей, потому что a 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
Обновление для Python 3.6
n_items = take(n, d.items())
iteritemsследует заменить на itemsдля людей на Python 3
take()ли где-нибудь часть базы кода Python? Или это просто функция, которую вы определили здесь в своем ответе? Спрашивая, как будто это часть базы кода, я не могу его найти / импортировать. :)
Очень эффективный способ получить что-либо - объединить понимание списка или словаря с нарезкой. Если вам не нужно заказывать элементы (вам просто нужно n случайных пар), вы можете использовать понимание словаря следующим образом:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[: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]}
dictS Python не упорядочены, поэтому бессмысленно запрашивать «первые 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))
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 ().
Не видел его здесь. Не будет упорядочен, но синтаксически простейший, если вам нужно просто взять какие-то элементы из словаря.
n = 2
{key:value for key,value in d.items()[0:n]}
TypeError: 'dict_items' object is not subscriptable {key:value for key,value in stocks.items()[0:n]} (акции - это название моего словаря)
Чтобы получить верхние N элементов из вашего словаря Python, можно использовать следующую строку кода:
list(dictionaryName.items())[:N]
В вашем случае вы можете изменить его на:
list(d.items())[: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)]
в py3 это поможет
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
Это зависит от того, что «наиболее эффективно» в вашем случае.
Если вам просто нужна полуслучайная выборка из огромного словаря foo, используйте foo.iteritems()и берите из нее столько значений, сколько вам нужно, это ленивая операция, которая позволяет избежать создания явного списка ключей или элементов.
Если вам нужно сначала отсортировать ключи, нет способа использовать что-то вроде keys = foo.keys(); keys.sort()или sorted(foo.iterkeys()), вам придется создать явный список ключей. Затем нарезать или итерация через первую N keys.
Кстати, почему вас волнует «эффективный» способ? Вы профилировали свою программу? Если вы этого не сделали, используйте сначала очевидный и простой для понимания способ. Скорее всего, он будет работать хорошо, но не станет узким местом.
Вы можете подойти к этому несколькими способами. Если порядок важен, вы можете сделать это:
for key in sorted(d.keys()):
item = d.pop(key)
Если порядок не является проблемой, вы можете сделать это:
for i in range(4):
item = d.popitem()
valueа не itemдля ясности.
Словарь не поддерживает порядок, поэтому, прежде чем выбирать верхние N пар ключ-значение, давайте отсортируем его.
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)
считать диктат
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice сделает свое дело :) надеюсь, что это поможет!
Это может быть не очень элегантно, но у меня работает:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
x= 0
for key, val in d.items():
if x == 2:
break
else:
x += 1
# Do something with the first two key-value pairs
Я попробовал несколько ответов выше и заметил, что некоторые из них зависят от версии и не работают в версии 3.7.
Также отмечу, что начиная с версии 3.6 все словари упорядочены по последовательности вставки элементов.
Несмотря на то, что словари упорядочены, начиная с версии 3.6, некоторые из операторов, которые вы ожидаете работать с упорядоченными структурами, похоже, не работают.
Ответ на вопрос OP, который лучше всего сработал для меня.
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
lst = list(d.items())[:N]
def GetNFirstItems(self):
self.dict = {f'Item{i + 1}': round(uniform(20.40, 50.50), 2) for i in range(10)}#Example Dict
self.get_items = int(input())
for self.index,self.item in zip(range(len(self.dict)),self.dict.items()):
if self.index==self.get_items:
break
else:
print(self.item,",",end="")
Необычный подход, так как он выдает интенсивную временную сложность O (N).
list(d.items())[:4]. list () является базовой реализацией для многих ответов.