memfilter item dalam kamus python yang kuncinya berisi string tertentu

Saya seorang pembuat kode C yang mengembangkan sesuatu dengan python. Saya tahu bagaimana melakukan hal berikut di C (dan karenanya logika mirip C diterapkan pada python), tapi saya bertanya-tanya apa cara 'Python' melakukannya.

Saya memiliki kamus d, dan saya ingin mengoperasikan subset item, hanya item yang kuncinya (string) berisi substring tertentu.

yaitu logika C adalah:

for key in d:
    if filter_string in key:
        # do something
    else
        # do nothing, continue

Saya membayangkan versi python akan menjadi seperti itu

filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
    # do something

Saya telah menemukan banyak posting di sini mengenai pemfilteran kamus, tetapi tidak dapat menemukan satu pun yang melibatkan hal ini.

Kamus saya tidak bersarang dan saya menggunakan python 2.7


person memo    schedule 26.05.2014    source sumber
comment
stackoverflow.com/questions/2844516/python-filter-a-dictionary   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 21.11.2015
comment
Kemungkinan duplikat Cara memfilter kamus menurut fungsi kondisi sewenang-wenang?   -  person phunehehe    schedule 30.12.2017


Jawaban (5)


Bagaimana dengan pemahaman dict:

filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}

Jika Anda melihatnya, seharusnya sudah cukup jelas, karena bacaannya cukup mirip dengan bahasa Inggris.

Sintaks ini memerlukan Python 2.7 atau lebih tinggi.

Di Python 3, hanya ada dict.items(), bukan iteritems() jadi Anda akan menggunakan:

filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}
person Jonathon Reinhart    schedule 26.05.2014
comment
Kenapa tidak filtered_dict = {k:d[k] for k in d if filter_string in k}? - person thefourtheye; 26.05.2014
comment
@thefourtheye Saya akan menebak bahwa milik saya lebih cepat, karena tidak memunculkan pencarian d[k]. - person Jonathon Reinhart; 26.05.2014
comment
Juga, dia mengatakan # do something di komentar, tapi kami memberikan beberapa kunci di sini. - person thefourtheye; 26.05.2014
comment
Apakah kita memiliki iteritems di Python 3? Saya kira tidak demikian. Jadi, versi saya akan kompatibel, bukan? - person thefourtheye; 26.05.2014
comment
Di Python 3 Anda akan mengganti iteritems dengan items, yang sama dengan iteritems di Python 2.7. - person Jonathon Reinhart; 26.05.2014

Pilih apa pun yang paling mudah dibaca dan dipelihara. Hanya karena Anda dapat menuliskannya dalam satu baris bukan berarti Anda harus menuliskannya. Solusi Anda yang ada mendekati apa yang akan saya gunakan selain saya akan menggunakan iteritem untuk melewati pencarian nilai, dan saya benci jika saya dapat menghindarinya:

for key, val in d.iteritems():
    if filter_string not in key:
        continue
    # do something

Namun jika Anda benar-benar menginginkan sesuatu yang memungkinkan Anda mengulangi dict yang difilter maka saya tidak akan melakukan proses dua langkah untuk membuat dict yang difilter dan kemudian mengulanginya, melainkan menggunakan generator, karena apa yang lebih pythonic (dan mengagumkan) daripada sebuah generator?

Pertama kita membuat generator kita, dan desain yang bagus mengharuskan kita membuatnya cukup abstrak untuk dapat digunakan kembali:

# The implementation of my generator may look vaguely familiar, no?
def filter_dict(d, filter_string):
    for key, val in d.iteritems():
        if filter_string not in key:
            continue
        yield key, val

Dan kemudian kita dapat menggunakan generator untuk menyelesaikan masalah Anda dengan baik dan bersih dengan kode sederhana dan mudah dimengerti:

for key, val in filter_dict(d, some_string):
    # do something

Singkatnya: generator itu luar biasa.

person Brendan F    schedule 26.05.2014

Anda dapat menggunakan fungsi filter bawaan untuk memfilter kamus, daftar, dll berdasarkan kondisi tertentu.

filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))

Keuntungannya adalah Anda dapat menggunakannya untuk struktur data yang berbeda.

person Pulkit    schedule 19.03.2018
comment
Perhatikan bahwa items: harus item: dalam definisi lambda. - person bkribbs; 01.09.2018
comment
Terima kasih @bkribbs karena telah menunjukkan kesalahannya. Saya telah memperbaikinya sekarang. - person Pulkit; 03.09.2018

Jonathon memberi Anda pendekatan menggunakan pemahaman dict dalam jawabannya. Berikut adalah pendekatan yang berkaitan dengan bagian melakukan sesuatu Anda.

Jika Anda ingin melakukan sesuatu dengan nilai kamus, Anda tidak memerlukan pemahaman kamus sama sekali:

Saya menggunakan iteritems() karena Anda menandai pertanyaan Anda dengan python-2.7

results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])

Sekarang hasilnya akan ada dalam daftar dengan some_function diterapkan pada setiap pasangan kunci/nilai kamus, yang memiliki foo di kuncinya.

Jika Anda hanya ingin menangani nilai dan mengabaikan kuncinya, ubah saja pemahaman daftarnya:

results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])

some_function bisa berupa panggilan apa pun, jadi lambda juga bisa digunakan:

results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])

Daftar bagian dalam sebenarnya tidak diperlukan, karena Anda juga dapat meneruskan ekspresi generator ke map:

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]
person Burhan Khalid    schedule 26.05.2014
comment
menarik. bagaimana some_function didefinisikan? dalam kasus pertama (k,v), apakah hanya membutuhkan dua parameter? kunci pertama lalu nilai? - person memo; 26.05.2014
comment
Ya, hanya bisa dihubungi. Jadi map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2)) - ini akan memberi Anda [4]. - person Burhan Khalid; 26.05.2014
comment
Ini benar, tetapi lebih pythonic daripada menggunakan map adalah pemahaman daftar. [f(v) for k, v in d.iteritems() if substring in k] Menurut saya ini jauh lebih mudah dibaca dan efisien. - person Davidmh; 26.05.2014
comment
@memo Tidak diperlukan dua parameter, dibutuhkan satu parameter dengan dua elemen. Namun ada juga starmap yang akan diuraikan menjadi dua argumen ini adalah iterator yang malas (harus diulang sebelum dijalankan, yaitu results = list(starmap(...)) atau for result in starmap(...): ...). - person nmclean; 26.05.2014

person    schedule
comment
Metode saya menggunakan iteritems() akan lebih efisien daripada items(). - person Jonathon Reinhart; 26.05.2014
comment
@Jonathin Reinhart Saya tidak mengetahuinya. Terima kasih. - person jspurim; 26.05.2014
comment
Hanya pada Python 2.7. Di Python 3 hanya ada hanya items(), yang bertindak seperti iteritems di Python 2.7. - person Jonathon Reinhart; 26.05.2014
comment
Pertanyaannya secara eksplisit untuk python 2.7 - person Brendan F; 26.05.2014