Mengakses elemen dict_keys berdasarkan indeks di Python3

131

Saya mencoba mengakses elemen dict_key dengan indeksnya:

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

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

Saya ingin mendapatkan foo.

sama dengan:

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

Bagaimana saya bisa melakukan ini?

fj123x
sumber
9
Di py3.x dict.keys()mengembalikan set seperti objek tampilan, bukan daftar (jadi, pengindeksan tidak mungkin). Gunakankeys = list(test)
Ashwini Chaudhary
ketika saya melakukan list (something_dict), urutan tuple adalah acak: contoh: list ({'foo': 'bar', 'hello': 'world'}) dapat mengembalikan: daftar (foo, hello) atau daftar (halo, foo), mengapa ini acak?
fj123x
7
Diktik tidak memiliki pesanan apa pun (Gunakan collections.OrderedDictjika Anda ingin kunci yang dipesan)
Ashwini Chaudhary
Diskusi menarik tentang keamanan utas di sini menggambarkan berbagai pendekatan untuk mengatasi masalah ini: blog.labix.org/2008/06/27/…
Paul

Jawaban:

161

Panggil list()kamus sebagai gantinya:

keys = list(test)

Dalam Python 3, dict.keys()metode ini mengembalikan objek tampilan kamus , yang bertindak sebagai satu set. Iterasi kamus secara langsung juga menghasilkan kunci, jadi mengubah kamus menjadi daftar menghasilkan daftar semua kunci:

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'
Martijn Pieters
sumber
3
Watch out for list (dict.keys ()) dengan Python 3 - Labix Blog dengan jelas menjelaskan apa masalahnya tanpa memberikan solusi. Ini luar biasa!
Brandon Bradley
@BrandonBradley: secara umum: mengandalkan tindakan tertentu menjadi atom adalah ide yang buruk, karena Python sangat dinamis. Kode Anda dapat dengan mudah dilewatkan dictsubkelas, misalnya, di mana .keys()ditangani dengan kode Python (misal, pengalihan utas dapat dilakukan).
Martijn Pieters
@BrandonBradley: terima kasih atas tautannya. Hanya solusi dari salah satu komentar untuk blog yang berfungsi untuk saya di Python3: diurutkan (dict.keys ()). Dalam Python2, dict.keys () akan mengembalikan daftar nilai kunci.
Good Will
2
@ GoodWill: sorted(dict)akan melakukan hal yang persis sama; menghasilkan daftar kunci dalam urutan diurutkan. list(dict)akan memberi Anda daftar dalam urutan kamus.
Martijn Pieters
1
atau untuk dapat menggunakankeys = [*test]
Alex78191
59

Bukan jawaban yang lengkap tapi mungkin petunjuk yang bermanfaat. Jika ini benar-benar item pertama yang Anda inginkan *, maka

next(iter(q))

jauh lebih cepat daripada

list(q)[0]

untuk dikte besar, karena semuanya tidak harus disimpan dalam memori.

Untuk 10.000.000 item, saya menemukannya hampir 40.000 kali lebih cepat.

* Item pertama dalam hal dict hanya item pseudo-acak sebelum Python 3.6 (setelah itu dipesan dalam implementasi standar, meskipun tidak disarankan untuk bergantung padanya).

Menandai
sumber
5
Ini selalu menjadi salah satu masalah terbesar saya dengan semuanya menjadi iterator di Py3. Ini jelas lebih efisien, tetapi begitu banyak kasus penggunaan menjadi "tidak bersih" dan rumit tanpa alasan. Misalnya, mengapa mereka tidak bisa hanya mendukung pengindeksan pada iterator, tanpa harus memiliki kehilangan kinerja?
Ehsan Kia
2

Saya ingin pasangan "kunci" & "nilai" dari item kamus pertama. Saya menggunakan kode berikut.

 key, val = next(iter(my_dict.items()))
Sheikh Abdul Wahid
sumber
0
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

Cara konvensional menambahkan kunci ke daftar yang ditentukan secara statis dan kemudian mengindeksnya untuk hal yang sama

pranav dua
sumber
2
Itu tidak salah, tetapi mengapa tidak ls = list(test.keys())? Saya merasa lebih sederhana.
Valentino
Ya, ini lebih efisien. Saya menulis ini hanya untuk menunjukkan keterbacaan.
pranav dua
0

Dalam banyak kasus, ini mungkin merupakan Masalah XY . Mengapa Anda mengindeks kunci kamus Anda berdasarkan posisi? Apakah Anda benar-benar perlu? Sampai baru-baru ini, kamus bahkan tidak dipesan dengan Python, sehingga mengakses elemen pertama adalah sewenang-wenang.

Saya baru saja menerjemahkan beberapa kode Python 2 ke Python 3:

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

yang tidak cantik, tapi juga tidak terlalu buruk. Pada awalnya, saya akan menggantinya dengan monster itu

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

sebelum saya menyadari ini jauh lebih baik ditulis sebagai

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

yang bekerja dengan baik.

Saya percaya bahwa dalam banyak kasus lain, pengindeksan kunci kamus berdasarkan posisi dapat dihindari. Meskipun kamus diperintahkan dalam Python 3.7, dengan mengandalkan itu tidak cantik. Kode di atas hanya berfungsi karena konten some_listbaru saja dihasilkan dari konten d.

Perhatikan kode Anda dengan saksama jika Anda benar-benar perlu mengakses disk_keyselemen dengan indeks. Mungkin Anda tidak perlu melakukannya.

gerrit
sumber
0

Coba ini

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

Hasilnya terlihat seperti ini. ['foo', 'hello']

Anda dapat menemukan lebih banyak solusi yang mungkin di sini .

Shirantha Madusanka
sumber