Saya memiliki struktur kamus yang kompleks yang ingin saya akses melalui daftar kunci untuk membahas item yang benar.
dataDict = {
"a":{
"r": 1,
"s": 2,
"t": 3
},
"b":{
"u": 1,
"v": {
"x": 1,
"y": 2,
"z": 3
},
"w": 3
}
}
maplist = ["a", "r"]
atau
maplist = ["b", "v", "y"]
Saya telah membuat kode berikut yang berfungsi tetapi saya yakin ada cara yang lebih baik dan lebih efisien untuk melakukan ini jika ada yang punya ide.
# Get a given data from a dictionary with position provided as a list
def getFromDict(dataDict, mapList):
for k in mapList: dataDict = dataDict[k]
return dataDict
# Set a given data in a dictionary with position provided as a list
def setInDict(dataDict, mapList, value):
for k in mapList[:-1]: dataDict = dataDict[k]
dataDict[mapList[-1]] = value
python
list
dictionary
kolergy
sumber
sumber
Jawaban:
Gunakan
reduce()
untuk melintasi kamus:dan gunakan kembali
getFromDict
untuk menemukan lokasi untuk menyimpan nilai untuksetInDict()
:Semua kecuali elemen terakhir
mapList
diperlukan untuk menemukan kamus 'induk' untuk menambahkan nilai, lalu gunakan elemen terakhir untuk mengatur nilai ke tombol kanan.Demo:
Perhatikan bahwa panduan gaya Python PEP8 menentukan nama fungsi snake_case . Di atas berfungsi sama baiknya untuk daftar atau campuran kamus dan daftar, sehingga nama harus benar-benar
get_by_path()
danset_by_path()
:sumber
try:
, diexcept (KeyError, IndexError): return default_value
sekitarreturn
baris saat ini .dict.get()
perubahan semantik, karena itu mengembalikanNone
daripada menaikkanKeyError
untuk nama yang hilang. Setiap nama berikutnya kemudian memicuAttributeError
.operator
adalah perpustakaan standar, tidak perlu menghindarinya di sini.from functools import reduce
.for
loop. Lihat kutipan dari What's New In Python 3.0 .KeyError
) - lihat jawaban @ eafit untuk solusiJadi mengapa tidak menggunakan metode yang disarankan dari pertanyaan kolergy untuk mendapatkan nilai:
Dan kode dari jawaban @ eafit untuk menetapkan nilai:
Keduanya bekerja dengan lurus di python 2 dan 3
sumber
getFromDict
memiliki potensi untuk menghancurkan penelepondataDict
. Saya akancopy.deepcopy(dataDict)
terlebih dahulu. Tentu saja, (seperti yang tertulis) perilaku ini diinginkan dalam fungsi kedua.Menggunakan pengurangan itu pintar, tetapi metode set OP mungkin memiliki masalah jika kunci induk tidak ada sebelumnya dalam kamus bersarang. Karena ini adalah posting SO pertama yang saya lihat untuk subjek ini di pencarian google saya, saya ingin membuatnya sedikit lebih baik.
Metode set di ( Menetapkan nilai dalam kamus python bersarang diberikan daftar indeks dan nilai ) tampaknya lebih kuat untuk kehilangan kunci orangtua. Untuk menyalinnya:
Juga, akan lebih mudah untuk memiliki metode yang melintasi pohon kunci dan mendapatkan semua jalur kunci absolut, yang telah saya buat:
Salah satu penggunaannya adalah untuk mengkonversi pohon bersarang ke panda DataFrame, menggunakan kode berikut (dengan asumsi bahwa semua daun dalam kamus bersarang memiliki kedalaman yang sama).
sumber
nested_set
?Perpustakaan ini mungkin bermanfaat: https://github.com/akesterson/dpath-python
sumber
Bagaimana kalau menggunakan fungsi rekursif?
Untuk mendapatkan nilai:
Dan untuk menetapkan nilai:
sumber
Gaya Python murni, tanpa impor apa pun:
Keluaran
sumber
Cara alternatif jika Anda tidak ingin meningkatkan kesalahan jika salah satu kunci tidak ada (sehingga kode utama Anda dapat berjalan tanpa gangguan):
Dalam hal ini, jika salah satu kunci input tidak ada, Tidak ada yang dikembalikan, yang dapat digunakan sebagai tanda centang pada kode utama Anda untuk melakukan tugas alternatif.
sumber
Alih-alih mengambil hit kinerja setiap kali Anda ingin mencari nilai, bagaimana kalau Anda meratakan kamus sekali kemudian cukup mencari kunci seperti
b:v:y
Dengan cara ini Anda bisa mencari barang
flat_dict['b:v:y']
yang akan digunakan1
.Dan alih-alih melintasi kamus pada setiap pencarian, Anda mungkin dapat mempercepat ini dengan meratakan kamus dan menyimpan output sehingga pencarian dari awal akan berarti memuat kamus yang diratakan dan hanya melakukan pencarian kunci / nilai tanpa traversal.
sumber
Memecahkan ini dengan rekursi:
Menggunakan contoh Anda:
sumber
Bagaimana dengan memeriksa dan mengatur elemen dict tanpa memproses semua indeks dua kali?
Larutan:
Contoh alur kerja:
Uji
sumber
Sangat terlambat ke pesta, tetapi memposting kalau-kalau ini dapat membantu seseorang di masa depan. Untuk kasus penggunaan saya, fungsi berikut bekerja paling baik. Berfungsi untuk menarik semua tipe data dari kamus
dict adalah kamus yang mengandung nilai kami
daftar adalah daftar "langkah-langkah" menuju nilai kami
sumber
Sangat memuaskan melihat jawaban ini karena memiliki dua metode statis untuk mengatur & mendapatkan atribut bersarang. Solusi ini jauh lebih baik daripada menggunakan pohon bersarang https://gist.github.com/hrldcpr/2012250
Inilah implementasi saya.
Penggunaan :
Untuk mengatur panggilan atribut bersarang
sattr(my_dict, 1, 2, 3, 5) is equal to my_dict[1][2][3][4]=5
Untuk mendapatkan panggilan atribut bersarang
gattr(my_dict, 1, 2)
sumber
Saya sarankan Anda menggunakan
python-benedict
untuk mengakses item bersarang menggunakan keypath.Instal menggunakan
pip
:Kemudian:
Berikut dokumentasi lengkapnya: https://github.com/fabiocaccamo/python-benedict
sumber
Jika Anda juga ingin kemampuan untuk bekerja dengan json sewenang-wenang termasuk daftar dan dikte bersarang, dan menangani jalur pencarian yang tidak valid dengan baik, inilah solusi saya:
sumber
metode untuk merangkai string:
sumber
Memperluas pendekatan @DomTomCat dan lainnya, fungsional ini (yaitu, mengembalikan data yang dimodifikasi melalui deepcopy tanpa mempengaruhi input) setter dan mapper berfungsi untuk bersarang
dict
danlist
.penyetel:
mapper:
sumber
Anda dapat menggunakan
eval
fungsi dalam python.Penjelasan
Untuk kueri contoh Anda:
maplist = ["b", "v", "y"]
nestq
akan berada"nest['b']['v']['y']"
dinest
tempat kamus bersarang.Fungsi
eval
builtin mengeksekusi string yang diberikan. Namun, penting untuk berhati-hati tentang kemungkinan kerentanan yang muncul dari penggunaaneval
fungsi. Diskusi dapat ditemukan di sini:Dalam
nested_parse()
fungsinya, saya telah memastikan bahwa tidak ada__builtins__
global yang tersedia dan hanya variabel lokal yang tersedia adalahnest
kamus.sumber
Anda dapat menggunakan pydash:
https://pydash.readthedocs.io/en/latest/api.html
sumber