Python - Повернення першого N ключа: пари значень з dict


108

Розглянемо наступний словник, d:

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

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


1
Обережність. Здається, у відповідях багато дезінформації. Мої тести показують, що не одне рішення швидше, ніж list(d.items())[:4]. list () - основна реалізація багатьох відповідей.
BSalita

Відповіді:


114

Немає такого поняття "перших 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


Оновлення для Python 3.6

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

42
Я вважаю, що його iteritemsслід замінити itemsна людей на Python 3
Моніка Хеднек

1
@MonicaHeddneck, геніальний, дякую за додавання цього коментаря.
Карл Бейкер

12
Тут для початківців - take()десь є частина бази коду python? Або це суто функція, яку ви визначили у своїй відповіді тут? Запитуючи, ніби це частина бази коду, я не в змозі його знайти / імпортувати. :)
Скотт Борден

81

Дуже ефективний спосіб отримати що-небудь - поєднувати розуміння списку чи словника з нарізкою. Якщо вам не потрібно замовляти товари (просто потрібно 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]}

Як правило, таке розуміння завжди проходить швидше, ніж еквівалентний цикл "для 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]}

2
Цей варіант є кращим рішенням, якщо ви хочете вибрати N багато ключів: пара значень як словник, а не як список
fermat4214

1
@ fermat4214 Це проблема, якщо весь мій словник роздруковується, коли я запускаю будь-яку з цих команд?
Тед Тейлор життя

список (мій вирок) [: 2] є марним, якщо вам не потрібно сортувати словник і потрібні лише перші 2 елементи. Що робити, якщо словник має 1 мільйон пар кВ? Перетворення всієї справи в список дорого. Рішення Марка Байєрса набагато краще.
JJ

Це має бути рішення!
Гюнтер

14

Python's 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))

Не виглядає лінивим. Займає в 2 рази більше, ніж `список (d.items ()) [: 4]
BSalita

12
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) у ітератор, а потім повторіть його з наступним ().


2
Фантастична відповідь, це єдина відповідь на цій сторінці, яка працювала на мене і також читається. Також я можу переконатися, що це працює за допомогою Python 3, на що деякі старіші відповіді не здаються.
cdahms

7

Не бачив тут. Не буде впорядковано, але найпростіше синтаксично, якщо вам потрібно просто взяти деякі елементи зі словника.

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

7
Я спробував вам код, але я отримую цю помилку: TypeError: 'dict_items' object is not subscriptable {key:value for key,value in stocks.items()[0:n]} (акції - це назва мого словника)
Moondra

2
@Moondra - Доводиться перетворювати у список перед тим, як переглядати елементи словника. Над кодом рядок працює, якщо {ключ: значення для ключа, значення у списку (d.items ()) [0: n]}
Rajesh Mappu

{A: N для (A, N) в [x for x in d.items ()] [: 4]}
фарид хафізов

6

Щоб отримати найпопулярніші N елементів зі свого словника python, можна скористатись наступним рядком коду:

list(dictionaryName.items())[:N]

У вашому випадку ви можете змінити його на:

list(d.items())[:4]

3

Див. 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)]



1

Це залежить від того, що є "найбільш ефективним" у вашому випадку.

Якщо ви просто хочете отримати напіввипадкову вибірку величезного словника foo, використовувати foo.iteritems()і взяти з нього стільки значень, скільки вам потрібно, це лінива операція, яка дозволяє уникнути створення явного списку ключів або елементів.

Якщо вам потрібно спочатку сортувати клавіші, не можна використовувати щось на зразок, keys = foo.keys(); keys.sort()або sorted(foo.iterkeys())вам доведеться скласти чіткий список ключів. Потім нарізати або ітерація через першу N keys.

До речі, чому ви дбаєте про «ефективний» спосіб? Ви профілювали свою програму? Якщо ви цього не зробили, спочатку скористайтеся очевидним і зрозумілим для вас способом. Швидше за все, це буде досить добре, не стаючи вузьким місцем.


Це було додатком до фінансової програми, і я намагаюся створити кожен рядок коду максимально ефективно. Я не розглядав програму і погоджуюся, що це, мабуть, не буде горлечко для пляшок, але я люблю просити ефективні рішення за замовчуванням. Дякую за відповідь.
Джейсон Стрімпель

0

Ви можете підійти до цього кількома способами. Якщо замовлення важливе, ви можете зробити це:

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

Якщо замовлення не хвилює, ви можете зробити це:

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

У першому фрагменті ви, мабуть, повинні зателефонувати, valueа не itemдля ясності.
agf

0

Словник не підтримує порядку, тому перед тим, як вибрати верхнє 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)

0

Для Python 3 і вище, для вибору перших n пар

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}

0

розглянути дикт

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

from itertools import islice
n = 3
list(islice(d.items(),n))

islice зробить трюк :) сподіваюся, що це допоможе!


0

Це може бути не дуже елегантно, але працює для мене:

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

0

Я спробував декілька відповідей вище та зазначу, що деякі з них залежать від версії і не працюють у версії 3.7.

Я також зазначу, що з 3.6 всі словники упорядковуються за послідовністю, в яку вставляються елементи.

Незважаючи на те, що словники замовляються з 3.6, деякі твердження, які ви очікуєте працювати з упорядкованими структурами, здається, не працюють.

Відповідь на питання ОП, яке найкраще працювало для мене.

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]

FYI, у 5 разів повільніше, ніжlst = list(d.items())[:N]
BSalita
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.