Python3'te indekse göre dict_keys öğesine erişim


131

Bir dict_key öğesinin dizinine göre erişmeye çalışıyorum:

test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys()  # dict_keys object

keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'

Almak istiyorum foo.

ile aynı:

keys[0]
TypeError: 'dict_keys' object does not support indexing

Bunu nasıl yapabilirim?


9
Py3.x dict.keys(), liste değil, görünüm nesnesi gibi bir küme döndürür (bu nedenle, indeksleme mümkün değildir). Kullanımkeys = list(test)
Ashwini Chaudhary

list (something_dict) yaptığımda, tuple sırası rastgeledir: örnek: list ({'foo': 'bar', 'merhaba': 'world'}) şunları döndürebilir: list (foo, merhaba) veya list (merhaba, foo), bu neden rastgele?
fj123x

7
Dicts'in herhangi bir sırası yok . ( collections.OrderedDictAnahtarları sipariş etmek istiyorsanız kullanın)
Ashwini Chaudhary

İş parçacığı güvenliği üzerine ilginç tartışma, bu sorunu çözmek için çeşitli yaklaşımları yeniden sınıflandırıyor
Paul

Yanıtlar:


161

list()Bunun yerine sözlüğü arayın :

keys = list(test)

Python 3'te, dict.keys()yöntem , bir küme görevi gören bir sözlük görünümü nesnesi döndürür . Sözlüğün üzerinde yinelendiğinde doğrudan anahtarlar da elde edilir, bu nedenle sözlüğü bir listeye dönüştürmek tüm tuşların bir listesini verir:

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'

3
Python 3'teki listeye (dict.keys ()) dikkat edin - Labix Blog , bir çözüm sunmadan sorunun ne olduğunu açıkça açıklar. Bu mükemmel!
Brandon Bradley

@BrandonBradley: Genel olarak konuşursak: Python çok dinamik olduğu için belirli eylemlerin atomik olmasına güvenmek zaten kötü bir fikir. Kodunuz, dictörneğin .keys()Python kodunda işlenen bir alt sınıfa kolayca geçirilebilir (örneğin, bir iş parçacığı anahtarı yer alabilir).
Martijn Pieters

@BrandonBradley: bağlantı için teşekkürler. Python3'te benim için yalnızca bu blog için yorumlardan birinin çözümü işe yarar: sıralı (dict.keys ()). Python2'de, dict.keys () anahtar değerlerinin bir listesini döndürür.
İyi Niyet

2
@GoodWill: sorted(dict)aynı şeyi yapardı; sıralı olarak bir anahtar listesi oluşturur. list(dict)listeyi sözlük sırasına göre verecektir.
Martijn Pieters

1
veya kullanabilirkeys = [*test]
Alex78191

59

Tam bir cevap değil ama belki de faydalı bir ipucu. Eğer gerçekten istediğiniz ilk öğeyse *, o zaman

next(iter(q))

daha hızlı

list(q)[0]

büyük diktler için, çünkü her şeyin hafızada saklanması gerekmiyor.

10.000.000 öğe için neredeyse 40.000 kat daha hızlı buldum.

* Bir diktenin Python 3.6'dan önce sadece sözde rastgele bir öğe olması durumunda ilk öğe (bundan sonra standart uygulamada sıralanmıştır, ancak buna güvenilmesi tavsiye edilmemektedir).


5
Bu, Py3'te her şeyin yineleyici hale gelmesiyle ilgili en büyük sorunumdan biri olmuştur. Kesinlikle daha verimlidir, ancak pek çok kullanım durumu sebepsiz yere "kirli" ve karmaşık hale gelir. Örneğin, neden bir performans kaybı yaşamadan yineleyicide indekslemeyi desteklemiyorlar?
Ehsan Kia

2

İlk sözlük öğesinin "anahtar" ve "değer" çiftini istedim. Aşağıdaki kodu kullandım.

 key, val = next(iter(my_dict.items()))

0
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

Anahtarları statik olarak tanımlanmış bir listeye eklemenin ve ardından aynı şekilde indekslemenin geleneksel yolu


2
Yanlış değil ama neden olmasın ls = list(test.keys())? Ben daha basit buluyorum.
Valentino

Evet, bu daha etkilidir. Bunu sadece okunabilirliği göstermek için yazdım.
pranav dua

0

Çoğu durumda, bu bir XY Sorunu olabilir . Neden sözlük anahtarlarınızı konuma göre indeksliyorsunuz? Gerçekten ihtiyacın var mı? Yakın zamana kadar, sözlükler Python'da bile sipariş edilmiyordu, bu nedenle ilk öğeye erişmek keyfi bir şeydi.

Az önce bazı Python 2 kodunu Python 3'e çevirdim:

keys = d.keys()
for (i, res) in enumerate(some_list):
    k = keys[i]
    # ...

bu hoş değil ama çok da kötü değil. İlk başta onu canavarla değiştirmek üzereydim

    k = next(itertools.islice(iter(keys), i, None))

farkına varmadan önce, bunların çok daha iyi yazıldığını

for (k, res) in zip(d.keys(), some_list):

hangi gayet iyi çalışıyor.

Diğer birçok durumda, sözlük anahtarlarının konuma göre endekslenmesinin önlenebileceğine inanıyorum. Sözlükler Python 3.7'de sıralanmasına rağmen, buna güvenmek hoş değil. Yukarıdaki kod yalnızca, öğesinin içeriği some_listyakın zamanda öğesinin içeriğinden üretildiği için çalışır d.

Dizine göre bir disk_keysöğeye gerçekten erişmeniz gerekiyorsa kodunuza iyice bakın. Belki gerek yok.


0

Bunu dene

keys = [next(iter(x.keys())) for x in test]
print(list(keys))

Sonuç şuna benziyor. ['foo', 'merhaba']

Daha olası çözümleri burada bulabilirsiniz .

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.