Akses elemen yang berubah-ubah dalam kamus dengan Python

507

Jika a mydicttidak kosong, saya mengakses elemen sewenang-wenang sebagai:

mydict[mydict.keys()[0]]

Apakah ada cara yang lebih baik untuk melakukan ini?

Stan
sumber
3
Apa yang dia katakan .. ini hanya benar-benar pertanyaan yang valid jika hanya ada satu elemen dalam dikt, atau Anda tidak peduli yang Anda dapatkan kembali.
kerajaan
5
Yup, saya hanya perlu mengakses elemen apa saja dalam dikt, jadi itu sebabnya saya ingin mengakses elemen pertama.
Stan
2
@Stan: tapi seperti kata Greg, tidak ada elemen "pertama" yang pasti dalam dikt. jadi mungkin Anda harus mengubah pertanyaan Anda, hanya untuk menjadi jelas
tdihp
10
Saya pikir ini adalah pertanyaan yang valid. Jika Anda perlu mengakses elemen arbitrer, dan Anda yakin bahwa diktnya tidak kosong, mungkin ide yang baik untuk meminta "pertama", karena jumlah item mungkin tidak diketahui.
kap
7
@MichaelScheper Anda harus cor ke daftar: list(mydict.keys())[0].
Daniel Moskovich

Jawaban:

600

Pada Python 3, non-destruktif dan berulang:

next(iter(mydict.values()))

Pada Python 2, non-destruktif dan berulang:

mydict.itervalues().next()

Jika Anda ingin berfungsi dalam Python 2 dan 3, Anda bisa menggunakan sixpaket:

six.next(six.itervalues(mydict))

meskipun pada titik ini cukup samar dan saya lebih suka kode Anda.

Jika Anda ingin menghapus item apa pun, lakukan:

key, value = mydict.popitem()

Perhatikan bahwa "pertama" mungkin bukan istilah yang sesuai di sini karena dictbukan tipe yang diurutkan dalam Python <3.6. Python 3.6+ dictsdipesan.

doublep
sumber
35
Bukankah maksud Anda dict.iterkeys().next()?
John Machin
12
@ John Machin: Yah, pertanyaannya sepertinya mengakses nilai yang terkait dengan kunci pertama, jadi itulah yang saya lakukan dalam jawabannya juga.
doublep
5
ini terlihat lebih baik: dict.values().__iter__().__next__():)
Vitaly Zdanevich
17
itu menjengkelkan bahwa dict.keys () tidak secara langsung dapat diubah.
semiomant
3
untuk popitem non-destruktif Anda dapat membuat salinan (dangkal):key, value = dict(d).popitem()
Pelle
140

Jika Anda hanya perlu mengakses satu elemen (menjadi yang pertama secara kebetulan, karena dikt tidak menjamin pemesanan) Anda cukup melakukan ini di Python 2 :

my_dict.keys()[0]     -> key of "first" element
my_dict.values()[0]   -> value of "first" element
my_dict.items()[0]    -> (key, value) tuple of "first" element

Harap perhatikan bahwa (setahu saya) Python tidak menjamin bahwa 2 panggilan berurutan ke salah satu metode ini akan menghasilkan daftar dengan urutan yang sama. Ini tidak didukung dengan Python3.

dalam Python 3 :

list(my_dict.keys())[0]     -> key of "first" element
list(my_dict.values())[0]   -> value of "first" element
list(my_dict.items())[0]    -> (key, value) tuple of "first" element
swK
sumber
90
Itu hanya bekerja di Python 2.x, untuk 3.x Anda harus menggunakanlist(my_dict.keys())[0]
alldayremix
6
Jadi, kelas kompleksitas apa ini? Tentunya list(my_dict.keys())[0]bukan malas?
Evgeni Sergeev
1
Untuk memperjelas, apa yang dimaksud @alldayremix dengan komentar itu adalah dalam python 3.x my_dict.function () hasilnya tidak mendukung pengindeksan, inilah mengapa pertama-tama kita harus mengubahnya menjadi daftar dan kemudian kita dapat menggunakan indeks [0]
Noki
57

Dalam python3, Caranya:

dict.keys() 

mengembalikan nilai dalam tipe: dict_keys (), kami akan mendapatkan kesalahan ketika mendapat anggota pertama kunci dict dengan cara ini:

dict.keys()[0]
TypeError: 'dict_keys' object does not support indexing

Akhirnya, saya mengonversi dict.keys () ke list @ 1st, dan mendapat anggota pertama dengan metode splice list:

list(dict.keys())[0]
Xb74Dkjb
sumber
Ini adalah solusi termudah dan bekerja di kedua python2 dan python3.
mattmilten
Untuk uang saya Saya mengatakan jawaban ini adalah yang paling intuitif
Thomas Valadez
Ya, tapi ini tidak menjawab pertanyaan OP, yaitu bagaimana mendapatkan di VALUES, bukan kunci.
Mike Williamson
1
@MikeWilliamson semoga sebagian besar pembaca akan tahu cara mendapatkan nilai yang sesuai, diberikan kunci, dari dict python.
eric
5
Untuk mendapatkan item yang arbitrer, bukan kunci arbitrer, Anda dapat melakukannya secara analog list(dict.values())[0].
jhin
24

untuk mendapatkan kunci

next(iter(mydict))

untuk mendapatkan nilai

next(iter(mydict.values()))

untuk mendapatkan keduanya

next(iter(mydict.items())) # or next(iter(mydict.viewitems())) in python 2

Dua yang pertama adalah Python 2 dan 3. Dua yang terakhir malas di Python 3, tetapi tidak dalam Python 2.

maxbellec
sumber
16

Seperti yang disebutkan lainnya, tidak ada "item pertama", karena kamus tidak memiliki urutan jaminan (mereka diimplementasikan sebagai tabel hash). Jika Anda ingin, misalnya, nilai yang sesuai dengan kunci terkecil, thedict[min(thedict)]akan melakukannya. Jika Anda peduli tentang urutan di mana kunci dimasukkan, yaitu, dengan "pertama" yang Anda maksudkan "dimasukkan paling awal", maka dalam Python 3.1 Anda dapat menggunakan collections.OrderedDict , yang juga dalam Python 2.7 yang akan datang; untuk versi Python yang lebih lama, unduh, instal, dan gunakan perintah dict backport (2.4 dan yang lebih baru) yang dapat Anda temukan di sini .

Python 3.7 Sekarang dikt adalah perintah penyisipan.

Alex Martelli
sumber
11

Bagaimana dengan ini. Belum disebutkan di sini.

py 2 & 3

a = {"a":2,"b":3}
a[list(a)[0]] # the first element is here
>>> 2
animaacija
sumber
5
dict.values()mengembalikan tampilan, jadi seharusnya O (1). list(a)mengembalikan daftar baru, jadi akan menjadi O (n).
boycy
Sepertinya juga tidak berfungsi di python2 jika a = {"a": {"1"}}
qasimzee
11

Mengabaikan masalah seputar pemesanan dikt, mungkin ini lebih baik:

next(dict.itervalues())

Dengan cara ini kami menghindari pencarian item dan membuat daftar kunci yang tidak kami gunakan.

Python3

next(iter(dict.values()))
Matt Joiner
sumber
2
nilai () akan membuat salinan semua nilai (seperti kunci () untuk kunci), jadi ini akan membuat banyak operasi O (n ^ 2).
Glenn Maynard
Jadi akankah versi OP? Saya akan mengubah ini untuk menggunakan iterator.
Matt Joiner
4
Ini hanya Python 2. Untuk Python 3, kita perlu next(iter(dict.values()))mendapatkan hasil yang sama tanpa membuat daftar.
kap
6

Dalam python3

list(dict.values())[0]
Oleg Matei
sumber
4
Apa yang terjadi jika kamus memiliki satu miliar entri? :)
Fábio Dias
2

Anda selalu dapat melakukan:

for k in sorted(d.keys()):
    print d[k]

Ini akan memberi Anda serangkaian kunci yang diurutkan secara konsisten (terkait dengan builtin .hash () saya kira) yang dapat Anda proses jika penyortiran memiliki arti bagi Anda. Itu berarti misalnya tipe numerik diurutkan secara konsisten bahkan jika Anda memperluas kamus.

CONTOH

# lets create a simple dictionary
d = {1:1, 2:2, 3:3, 4:4, 10:10, 100:100}
print d.keys()
print sorted(d.keys())

# add some other stuff
d['peter'] = 'peter'
d['parker'] = 'parker'
print d.keys()
print sorted(d.keys())

# some more stuff, numeric of different type, this will "mess up" the keys set order
d[0.001] = 0.001
d[3.14] = 'pie'
d[2.71] = 'apple pie'
print d.keys()
print sorted(d.keys())

Perhatikan bahwa kamus diurutkan saat dicetak. Tetapi set kunci pada dasarnya adalah sebuah hashmap!

Philipp Meier
sumber
2

Untuk Python 2 dan 3:

import six

six.next(six.itervalues(d))
oblalex
sumber
Ini tidak memberikan jawaban untuk pertanyaan itu. Untuk mengkritik atau meminta klarifikasi dari penulis, tinggalkan komentar di bawah posting mereka.
Martin Tournoij
Ini tepatnya menjawab pertanyaan Is there any better way to do this?secara singkat.
oblalex
Jawaban ini sudah diberikan dua kali, salah satunya sudah ada di situs ini selama hampir 5 tahun. Ini adalah komentar untuk jawaban lain (seperti pada: inilah cara meningkatkan jawaban agar berfungsi dengan kedua Python 2 & 3 ), dan bukan jawaban "baru". Sistem ulasan SO secara otomatis menempatkan catatan yang agak tidak membantu dalam kasus ini ...
Martin Tournoij
Tidak pak. Anda menambahkan varian ini ke jawaban 5 tahun hanya 17 jam yang lalu, 1 jam setelah saya menulis jawaban ini. Coba gunakan 'temukan' di halaman ini untuk kata 'enam' dan Anda hanya akan menemukan 6 kecocokan hanya dalam 2 jawaban ini. Lagi pula, apakah jawaban ini benar-benar mengganggu Anda? Saya pikir ini mungkin membantu orang lain di masa depan dan ini tidak masalah. Jadi, apa masalahnya?
oblalex
Itu karena IMHO jawaban ini seharusnya menjadi edit posting itu di tempat pertama. Tanpa hasil edit, orang harus menggulirkan sejumlah halaman ke bawah untuk melihat jawaban Anda; Menurut Anda apakah itu lebih berguna daripada mengedit jawaban yang sangat tervvvatif yang hampir persis sama dengan jawaban Anda?
Martin Tournoij
0
first_key, *rest_keys = mydict
pengguna1994083
sumber
11
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan terbatas dan segera. Sebuah penjelasan yang tepat akan sangat meningkatkan nilai jangka panjang dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini, dan akan membuatnya lebih bermanfaat untuk pembaca masa depan dengan lainnya, pertanyaan-pertanyaan serupa. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan, termasuk asumsi yang Anda buat.
Suraj Rao
-1

Tidak ada perpustakaan eksternal, berfungsi pada Python 2.7 dan 3.x:

>>> list(set({"a":1, "b": 2}.values()))[0]
1

Untuk kunci aribtrary, cukup tinggalkan .values ​​()

>>> list(set({"a":1, "b": 2}))[0]
'a'
Thomas Browne
sumber
-2

Subclassing dictadalah salah satu metode, meskipun tidak efisien. Di sini jika Anda memberikan bilangan bulat, integer akan kembali d[list(d)[n]], jika tidak, akses kamus seperti yang diharapkan:

class mydict(dict):
    def __getitem__(self, value):
        if isinstance(value, int):
            return self.get(list(self)[value])
        else:
            return self.get(value)

d = mydict({'a': 'hello', 'b': 'this', 'c': 'is', 'd': 'a',
            'e': 'test', 'f': 'dictionary', 'g': 'testing'})

d[0]    # 'hello'
d[1]    # 'this'
d['c']  # 'is'
jpp
sumber