Saya mencoba untuk menulis metode filter kustom yang mengambil sejumlah kwarg dan mengembalikan daftar yang berisi elemen dari daftar mirip database yang berisi kwarg tersebut .
Misalnya, d1 = {'a':'2', 'b':'3'}
and d2
= hal yang sama. d1 == d2
menghasilkan True. Tapi misalkan d2
= hal yang sama ditambah banyak hal lainnya. Metode saya harus dapat mengetahui apakah d1 dalam d2 , tetapi Python tidak dapat melakukannya dengan kamus.
Konteks:
Aku punya kelas Word, dan setiap objek memiliki sifat seperti word
, definition
, part_of_speech
, dan sebagainya. Saya ingin dapat memanggil metode filter pada daftar utama kata-kata ini, seperti Word.objects.filter(word='jump', part_of_speech='verb-intransitive')
. Saya tidak tahu cara mengelola kunci dan nilai ini secara bersamaan. Tetapi ini bisa memiliki fungsi yang lebih besar di luar konteks ini untuk orang lain.
sumber
d1.viewitems() <= d2.viewitems()
. Waktu berjalan menunjukkan peningkatan kinerja 3x lipat. Jika tidak dapat dicirikan, bahkan menggunakaniteritems()
alih-alihitems()
mengarah ke peningkatan sekitar 1,2x. Ini dilakukan menggunakan Python 2.7.items()
akan mengembalikan tampilan ringan, bukan salinan. Tidak diperlukan pengoptimalan lebih lanjut.Di Python 3, Anda bisa menggunakan
dict.items()
untuk mendapatkan tampilan set-like dari item dict. Anda kemudian dapat menggunakan<=
operator untuk menguji apakah satu tampilan adalah "subset" dari yang lain:Di Python 2.7, gunakan
dict.viewitems()
untuk melakukan hal yang sama:Di Python 2.6 dan di bawahnya Anda akan membutuhkan solusi yang berbeda, seperti menggunakan
all()
:sumber
d1.items() <= d2.items()
d1.items() <= d2.items()
sebenarnya membandingkan 2 daftar tupel, tanpa urutan tertentu, jadi hasil akhirnya mungkin tidak dapat diandalkan. Untuk alasan ini, saya beralih ke jawaban @blubberdiblub.d1.items() <= d2.items()
adalah perilaku yang tidak terdefinisi. Ini tidak didokumentasikan dalam dokumen resmi dan, yang paling penting, ini tidak diuji: github.com/python/cpython/blob/… Jadi ini tergantung pada implementasi.collections.abc.Set
tersedia"Catatan untuk orang yang membutuhkan ini untuk pengujian unit: ada juga
assertDictContainsSubset()
metode diTestCase
kelas Python .http://docs.python.org/2/library/unittest.html?highlight=assertdictcontainssubset#unittest.TestCase.assertDictContainsSubset
Namun itu sudah usang di 3.2, tidak yakin mengapa, mungkin ada penggantinya.
sumber
untuk kunci dan nilai, gunakan cek:
set(d1.items()).issubset(set(d2.items()))
jika Anda hanya perlu memeriksa kunci:
set(d1).issubset(set(d2))
sumber
d1={'a':1,'b':2}; d2={'a':2,'b':1}
-> potongan kedua akan kembaliTrue
...{'a', 'b'}
sebenarnya adalah bagian dari{'a', 'b'}
;)Untuk kelengkapan, Anda juga bisa melakukan ini:
Namun, saya tidak membuat klaim apa pun tentang kecepatan (atau ketiadaan) atau keterbacaan (atau ketiadaan).
sumber
small.viewitems() <= big.viewitems()
menjanjikan, tetapi dengan satu peringatan: jika program Anda juga dapat digunakan pada Python 2.6 (atau bahkan di bawah),d1.items() <= d2.items()
sebenarnya membandingkan 2 daftar tupel, tanpa urutan tertentu, jadi hasil akhirnya mungkin akan tidak dapat diandalkan. Untuk alasan itu, saya beralih ke jawaban @blubberdiblub. Suara positif.dict
kelas dasar? Bagaimana jika belum dan masih berperilaku seperti adict
? Bagaimana jikasmall
danbig
berisi nilai jenis yang berbeda pada kunci yang cocok yang masih berperilaku seperti dict?False
ketika nilai-nilai dari dicts yang diteruskan berbeda untuk kunci yang cocok). Atau dengan kata lain: Solusi untuk dicts bersarang belum tentu pengganti drop-in tergantung pada kasus penggunaan.konteks:
sumber
Fungsi saya untuk tujuan yang sama, melakukan ini secara rekursif:
Dalam contoh Anda,
dictMatch(d1, d2)
harus mengembalikan True meskipun d2 memiliki hal lain di dalamnya, ditambah itu berlaku juga untuk tingkat yang lebih rendah:Catatan: Mungkin ada solusi yang lebih baik yang menghindari
if type(pvalue) is dict
klausa dan berlaku untuk kasus yang lebih luas (seperti daftar hash dll). Juga rekursi tidak terbatas di sini jadi gunakan dengan resiko Anda sendiri. ;)sumber
Berikut adalah solusi yang juga berulang dengan benar ke dalam daftar dan set yang terdapat dalam kamus. Anda juga dapat menggunakan ini untuk daftar yang berisi penis dll ...
sumber
Masalah yang tampaknya langsung ini membuat saya menghabiskan beberapa jam dalam penelitian untuk menemukan solusi yang 100% andal, jadi saya mendokumentasikan apa yang saya temukan dalam jawaban ini.
Berbicara "Pythonic-ally",
small_dict <= big_dict
akan menjadi cara yang paling intuitif, tapi sayang sekali itu tidak akan berhasil .{'a': 1} < {'a': 1, 'b': 2}
tampaknya berfungsi dengan Python 2, tetapi tidak dapat diandalkan karena dokumentasi resmi secara eksplisit menyebutkannya. Lakukan pencarian "Hasil selain kesetaraan diselesaikan secara konsisten, tetapi tidak ditentukan sebaliknya." di bagian ini . Belum lagi, membandingkan 2 dicts dengan Python 3 menghasilkan pengecualian TypeError.Hal kedua yang paling intuitif adalah
small.viewitems() <= big.viewitems()
untuk Python 2.7 saja, dansmall.items() <= big.items()
untuk Python 3. Tapi ada satu peringatan: ini berpotensi buggy . Jika program Anda berpotensi digunakan pada Python <= 2.6,d1.items() <= d2.items()
ini sebenarnya membandingkan 2 daftar tupel, tanpa urutan tertentu, sehingga hasil akhirnya tidak dapat diandalkan dan menjadi bug yang tidak menyenangkan dalam program Anda. Saya tidak tertarik untuk menulis implementasi lain untuk Python <= 2.6, tetapi saya masih merasa tidak nyaman bahwa kode saya dilengkapi dengan bug yang diketahui (bahkan jika itu pada platform yang tidak didukung). Jadi saya meninggalkan pendekatan ini.Saya tenang dengan jawaban @blubberdiblub (Penghargaan diberikan kepadanya):
def is_subdict(small, big): return dict(big, **small) == big
Perlu ditunjukkan bahwa, jawaban ini bergantung pada
==
perilaku antar dicts, yang didefinisikan dengan jelas dalam dokumen resmi, oleh karena itu harus berfungsi di setiap versi Python . Pergi cari:sumber
Berikut solusi rekursif umum untuk masalah yang diberikan:
CATATAN: Kode asli akan gagal dalam kasus tertentu, kredit untuk perbaikan diberikan ke @ olivier-melançon
sumber
if not set(value) <= set(superset[key])
Jika Anda tidak keberatan menggunakan
pydash
adais_match
ada yang tidak tepat:sumber
Saya tahu pertanyaan ini sudah tua, tetapi inilah solusi saya untuk memeriksa apakah satu kamus bersarang adalah bagian dari kamus bersarang lainnya. Solusinya rekursif.
sumber
Fungsi ini berfungsi untuk nilai yang tidak dapat dicirikan. Saya juga menganggapnya jelas dan mudah dibaca.
sumber
Implementasi rekursif singkat yang berfungsi untuk kamus bersarang:
Ini akan memakan penis a dan b. Jika ada yang tahu cara yang baik untuk menghindarinya tanpa menggunakan solusi berulang sebagian seperti dalam jawaban lain, tolong beri tahu saya. Saya akan membutuhkan cara untuk membagi dikt menjadi kepala dan ekor berdasarkan kunci.
Kode ini lebih berguna sebagai latihan pemrograman, dan mungkin jauh lebih lambat daripada solusi lain di sini yang menggabungkan rekursi dan iterasi. Solusi @ Nutcrer cukup bagus untuk kamus bersarang.
sumber
a
(dan nilai pertama berikutnya) yangpopitem
ditemukan. Itu juga harus memeriksa item lain pada tingkat yang sama. Saya punya sepasang penis bersarang yang mengembalikan jawaban yang salah. (sulit untuk menyajikan contoh bukti masa depan di sini, karena bergantung pada urutanpopitem
)Gunakan objek pembungkus ini yang memberikan perbandingan parsial dan perbedaan yang bagus:
sumber