Python - İlk N anahtarını döndür: dict'deki değer çiftleri


109

Şu sözlüğü düşünün, d:

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

İlk N anahtarını döndürmek istiyorum: d'den değer çiftleri (bu durumda N <= 4). Bunu yapmanın en verimli yöntemi nedir?


1
Dikkat. Cevaplarda çok fazla yanlış bilgi var gibi görünüyor. Testlerim, tek bir çözümün daha hızlı olmadığını gösteriyor list(d.items())[:4]. list (), yanıtların çoğunun altında yatan uygulamadır.
BSalita

Yanıtlar:


115

"İlk n" anahtarları diye bir dictşey yoktur çünkü a hangi anahtarların ilk olarak eklendiğini hatırlamaz.

Yine de herhangi n anahtar / değer çifti alabilirsiniz :

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

Bu take, itertoolstariflerden uygulanmasını kullanır :

from itertools import islice

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

Çevrimiçi çalıştığını görün: ideone


Python 3.6 Güncellemesi

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

42
Ben inanmak iteritemsile değiştirilmesi gerekir itemsPython 3 millet
Monica Heddneck

1
@MonicaHeddneck, harika, bu yorumu eklediğiniz için teşekkürler.
Karl Baker

12
Burada acemi - herhangi take()bir yerde python kod tabanının bir parçası mı? Yoksa tamamen burada cevabınızda tanımladığınız işlev mi? Kod tabanının bir parçasıymış gibi sorarak, onu bulamıyorum / içeri aktaramıyorum. :)
Scott Borden

81

Herhangi bir şeyi geri almanın çok etkili bir yolu, liste veya sözlük anlamalarını dilimleme ile birleştirmektir. Öğeleri sipariş etmeniz gerekmiyorsa (sadece n rastgele çift istiyorsanız), aşağıdaki gibi bir sözlük anlayışı kullanabilirsiniz:

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

Genel olarak, böyle bir anlama, eşdeğer "for x in y" döngüsünden her zaman daha hızlıdır. Ayrıca, sözlük tuşlarının bir listesini yapmak için .keys () kullanarak ve bu listeyi dilimleyerek, yeni sözlüğü oluştururken gereksiz tuşlara 'dokunmaktan' kaçınırsınız.

Anahtarlara (yalnızca değerler) ihtiyacınız yoksa, bir liste anlayışı kullanabilirsiniz:

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

Değerlerin anahtarlarına göre sıralanmasına ihtiyacınız varsa, bu çok fazla sorun değildir:

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

veya anahtarlara da ihtiyacınız varsa:

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

2
Liste olarak değil, sözlük olarak N sayıda anahtar: değer çifti seçmek istiyorsanız, bu daha iyi bir çözümdür
fermat4214

1
@ fermat4214 Bu komutlardan herhangi birini çalıştırdığımda sözlüğümün tamamının yazdırılması bir sorun olur mu?
Ted Taylor of Life

list (mydict) [: 2] sözlüğü sıralamanız gerekmiyorsa ve yalnızca ilk 2 öğeye ihtiyacınız varsa savurganlık sağlar. Sözlüğün 1 mil kv çifti varsa ne olur? Her şeyi bir listeye dönüştürmek pahalıdır. Mark Byers'ın çözümü çok daha iyi.
JJ

Çözüm bu olmalı!
Guenter

14

Python’lar dictsıralı değildir, bu yüzden "ilk N" tuşlarını istemenin bir anlamı yoktur.

collections.OrderedDictO ihtiyacınız buysa sınıf mevcuttur. İlk dört unsurunu verimli bir şekilde elde edebilirsiniz.

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.isliceherhangi bir yineleyiciden tembel olarak bir parça öğe almanızı sağlar. Sonucun yeniden kullanılabilir olmasını istiyorsanız, bunu bir listeye veya bunun gibi bir şeye dönüştürmeniz gerekir:

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

Tembel görünmüyorum. "List (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))

Temel olarak, görünümü (dict_items) bir yineleyiciye dönüştürün ve ardından next () ile yineleyin.


2
Harika cevap, bu sayfadaki benim için çalışan ve aynı zamanda okunabilir olan tek cevap bu. Ayrıca, bunun bazı eski cevapların görünmediği Python 3 ile çalıştığını doğrulayabilirim.
cdahms

7

Burada görmedim. Bir sözlükten bazı unsurları almanız gerekiyorsa, sıralanmayacak, ancak sözdizimsel olarak en basit olanıdır.

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

7
Kodunuzu denedim ama şu hatayı alıyorum: TypeError: 'dict_items' object is not subscriptable {key:value for key,value in stocks.items()[0:n]} (hisse senetleri sözlüğümün adıdır)
Moondra

2
@Moondra - Sözlük öğelerini çalıştırmadan önce listeye dönüştürmeniz gerekir. Kodun yukarısındaki satır, {key: key için değer, listedeki değer (d.items ()) [0: n]}
Rajesh Mappu

{A: N için (A, N) içinde [x için x için d.items ()] [: 4]}
farid khafizov

6

Python sözlüğünüzden en iyi N öğeyi almak için aşağıdaki kod satırını kullanabilirsiniz:

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

Sizin durumunuzda bunu şu şekilde değiştirebilirsiniz:

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

3

Sözlükleri sıralamak için PEP 0265'e bakınız . Ardından yukarıda belirtilen yinelenebilir kodu kullanın.

Sıralanan anahtar / değer çiftlerinde daha fazla verimliliğe ihtiyacınız varsa. Farklı bir veri yapısı kullanın. Diğer bir deyişle, sıralı düzeni ve anahtar / değer ilişkilerini koruyan.

Örneğin

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)]

3

py3'te hile yapacak

{A:N for (A,N) in [x for x in d.items()][:4]}

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


2

sadece zip kullanarak bir cevap ekleyin,

{k: d[k] for k, _ in zip(d, range(n))}

1

Bu, sizin durumunuzda neyin 'en verimli' olduğuna bağlıdır.

Yalnızca büyük bir sözlüğün yarı rastgele bir örneğini istiyorsanız, istediğiniz kadar değeri fookullanın foo.iteritems()ve ondan alın, bu, açık bir anahtar veya öğe listesi oluşturmayı önleyen tembel bir işlemdir.

Önce anahtarları sıralamanız gerekiyorsa, keys = foo.keys(); keys.sort()veya gibi bir şey kullanmanın yolu yoktur sorted(foo.iterkeys()), açık bir anahtar listesi oluşturmanız gerekir. Ardından ilk N'ye kadar dilimleyin veya yineleyin keys.

BTW neden 'verimli' yolu önemsiyorsunuz? Programınızın profilini çıkardınız mı? Eğer yapmadıysanız, ilk önce apaçık ve anlaşılması kolay yolu kullanın . Darboğaz haline gelmeden oldukça iyi iş çıkarması ihtimali vardır.


Bu bir finans programına bir uygulamaydı ve her kod satırını olabildiğince verimli bir şekilde oluşturmaya çalışıyorum. Programın profilini çıkarmadım ve bunun muhtemelen dar boğaz olmayacağını kabul ettim, ancak varsayılan olarak verimli çözümler istemeyi seviyorum. Cevap için teşekkürler.
Jason Strimpel

0

Buna birkaç yoldan yaklaşabilirsiniz. Sipariş önemliyse, bunu yapabilirsiniz:

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

Sipariş bir sorun değilse, bunu yapabilirsiniz:

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

İlk kod parçacığında, muhtemelen netlik sağlamak valueyerine onu aramalısınız item.
agf

0

Sözlük sıralamayı korumaz, bu nedenle ilk N anahtar-değer çiftini seçmeden önce sıralı yapmasına izin verin.

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

Şimdi, aşağıdaki gibi yöntem yapısını kullanarak en üst 'N' öğelerini alabiliriz:

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

ilk 2 öğeyi almak için şu yapıyı kullanın:

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 ve üstü için, İlk n Çiftleri seçmek için

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

0

bir emir düşün

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

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

islice hile yapacak :) umarım yardımcı olur!


0

Bu çok zarif olmayabilir ama benim için işe yarıyor:

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

Yukarıdaki cevaplardan birkaçını denedim ve bazılarının versiyona bağlı olduğunu ve 3.7 versiyonunda çalışmadığını not ettim.

3.6'dan beri tüm sözlüklerin öğelerin eklendiği sıraya göre sıralandığını da not ediyorum.

3.6'dan beri sözlükler sipariş edilmesine rağmen, sıralı yapılarla çalışmayı beklediğiniz bazı ifadeler işe yaramıyor gibi görünüyor.

Benim için en çok işe yarayan OP sorusunun cevabı.

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

Bilginize, lst = list(d.items())[:N]
şundan

0
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="")

Yoğun O (N) zaman karmaşıklığı verdiği için alışılmadık yaklaşım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.