Рассмотрим следующий словарь, 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", потому что 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 случайных пар), вы можете использовать понимание словаря следующим образом:
# 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]}
Python dict
не упорядочены, поэтому бессмысленно запрашивать "первые 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().
См. 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]}
Это зависит от того, что "наиболее эффективно" в вашем случае.
Если вам просто нужен полуслучайный образец огромного словаря 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()
Словарь не поддерживает порядок, поэтому перед тем, как выбрать верхние пары ключей ключа 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)
Для Python 3 и выше, Чтобы выбрать первые n пар
n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}
считать диктом
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
Islice сделает свое дело :) надеюсь, это поможет!
просто добавьте ответ, используя почтовый индекс,
{k: d[k] for k, _ in zip(d, range(n))}