পাইথন অভিধানে আইটেমগুলি ফিল্টার করে যেখানে কীগুলিতে একটি নির্দিষ্ট স্ট্রিং থাকে


97

আমি সি সি কোডার পাইথনের কিছু বিকাশ করছি। আমি সিগুলিতে কীভাবে নিম্নলিখিতগুলি করতে হয় তা জানি (এবং সেইজন্য সি-এর মতো যুক্তিতে পাইথনটি প্রয়োগ করা হয়েছিল) তবে আমি ভাবছি এটি করার 'পাইথন' পদ্ধতিটি কী।

আমার কাছে একটি অভিধান ডি আছে এবং আমি আইটেমগুলির একটি উপসেট চালনা করতে চাই, কেবল যারা (স্ট্রিং) এর নির্দিষ্ট একটি স্ট্রিং থাকে।

অর্থাত সি যুক্তিটি হ'ল:

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

আমি কল্পনা করছি পাইথন সংস্করণটি এমন কিছু হবে

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

ফিল্টারিং অভিধান সম্পর্কিত আমি এখানে অনেকগুলি পোস্ট পেয়েছি, তবে এটির সাথে জড়িত কোনওটি খুঁজে পাইনি।

আমার অভিধানটি নেস্টেড নয় এবং আমি পাইথন ২.7 ব্যবহার করছি



উত্তর:


187

কিভাবে একটি ডিক বোঝাপড়া সম্পর্কে :

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

আপনি এটি দেখতে পাচ্ছেন, এটি স্ব-বর্ণনামূলক হওয়া উচিত, কারণ এটি বেশ ভাল ইংরেজির মতো পড়ে।

এই সিনট্যাক্সটির জন্য পাইথন ২.7 বা তারও বেশি প্রয়োজন।

পাইথন 3 এ কেবল আছে dict.items(), iteritems()তাই আপনি এটি ব্যবহার করবেন না :

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

4
কেন হবে না filtered_dict = {k:d[k] for k in d if filter_string in k}?
thefourtheye

4
@ থেফোর্তে আমি অনুমান করতে যাচ্ছি যে খনিটি দ্রুততর, কারণ এটি চেহারাটিকে অন্তর্ভুক্ত করে না d[k]
জোনাথন রাইনহার্ট

এছাড়াও, তিনি # do somethingমন্তব্যে বলেছেন , তবে আমরা এখানে কয়েকটি কী রেখেছি।
thefourtheye

iteritemsপাইথন 3 এ আমাদের কি আছে ? আমি তাই মনে করি না. তাহলে, আমার সংস্করণটি উপযুক্ত হবে, না?
thefourtheye

4
পাইথন 3 আপনি প্রতিস্থাপন করবে iteritemsসঙ্গে items, যা পাইথন 2.7 এর হিসাবে একই iteritems
জোনাথন রাইনহার্ট

18

সর্বাধিক পঠনযোগ্য এবং সহজেই বজায় রাখা যায় তার জন্য যান। আপনি একক লাইনে এটি লিখতে পারার অর্থ এই নয় যে আপনার উচিত। আপনার বিদ্যমান সমাধানটি আমি মূল্যবোধটি এড়াতে ব্যবহারকারীর আইট্রেটেমগুলি বাদে অন্যটি ব্যবহার করতে পারি তার কাছে, এবং আমি যদি এড়াতে পারি তবে আমি নেস্টেড আইফএসকে ঘৃণা করি:

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

তবে আপনি যদি সত্যিই কোনও ফিল্টারড ডিকের মাধ্যমে পুনরাবৃত্তি করতে চান তবে আমি ফিল্টারড ডিক তৈরির এবং তার মাধ্যমে পুনরাবৃত্ত করার দুটি ধাপ প্রক্রিয়া করব না, পরিবর্তে একটি জেনারেটর ব্যবহার করব কারণ এর চেয়ে বেশি অজগর (এবং ভয়ঙ্কর) কী একটি জেনারেটর?

প্রথমে আমরা আমাদের জেনারেটর তৈরি করি এবং ভাল ডিজাইন নির্দেশ দেয় যে আমরা এটিকে পুনরায় ব্যবহারযোগ্য হিসাবে যথেষ্ট বিমূর্ত করে তুলেছি:

# 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

এবং তারপরে আমরা জেনারেটরটি সহজ, বোধগম্য কোড দিয়ে আপনার সমস্যাটিকে সুন্দর এবং পরিষ্কার করে সমাধান করতে ব্যবহার করতে পারি:

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

সংক্ষেপে: জেনারেটর দুর্দান্ত।


11

নির্দিষ্ট শর্তের ভিত্তিতে আপনি অভিধান, তালিকা ইত্যাদি ফিল্টার করতে অন্তর্নির্মিত ফিল্টার ফাংশনটি ব্যবহার করতে পারেন ।

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

সুবিধাটি হ'ল আপনি এটি বিভিন্ন ডেটা স্ট্রাকচারের জন্য ব্যবহার করতে পারেন।


নোট যে ল্যাম্বডা সংজ্ঞা items:হতে হবে item:
বিকাববস

ত্রুটিটি নির্দেশ করার জন্য আপনাকে @bkribbs ধন্যবাদ। আমি এখন এটি সংশোধন করেছি।
পুলকিত

8
input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}

4
আমার ব্যবহার পদ্ধতিটি iteritems()আরও দক্ষ হতে চলেছে items()
জোনাথন রাইনহার্ট

@ জোনাথিন রেইনহার্ট আমি এটি সম্পর্কে জানতাম না। ধন্যবাদ
jspurim

4
পাইথন ২.7 এ কেবল। পাইথন 3-তে কেবল রয়েছে items() , যা পাইথন ২.7 এর মতো কাজ করে iteritems
জোনাথন রেইনার্ট

4
প্রশ্নটি স্পষ্টভাবে অজগর 2.7
ব্রেন্ডন এফ

7

জোনাথন আপনাকে ডিক সংজ্ঞা ব্যবহার করে একটি দৃষ্টিভঙ্গি দিয়েছে তার উত্তরে । এখানে এমন একটি দৃষ্টিভঙ্গি দেওয়া হয়েছে যা আপনার কিছু অংশ নিয়ে কাজ করে।

আপনি যদি অভিধানের মানগুলি নিয়ে কিছু করতে চান তবে আপনার অভিধানের কোনও বোঝার দরকার নেই:

iteritems(আপনি যেহেতু আপনার প্রশ্নটি ট্যাগ করেছেন আমি ব্যবহার করছি )

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

এখন ফলাফলটি একটি তালিকায় থাকবে some_function অভিধান প্রতিটি কী / মান জোড়া, যে প্রয়োগ fooতার কী হবে।

আপনি যদি কেবল মানগুলি নিয়ে কাজ করতে চান এবং কীগুলি উপেক্ষা করতে চান তবে কেবল তালিকা উপলব্ধিটি পরিবর্তন করুন:

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

some_function যে কোনও কলযোগ্য হতে পারে, সুতরাং একটি ল্যাম্বডা পাশাপাশি কাজ করবে:

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

অভ্যন্তরীণ তালিকাটি আসলে প্রয়োজন হয় না, কারণ আপনি মানচিত্রে একটি জেনারেটর এক্সপ্রেশনও পাস করতে পারেন :

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]

মজাদার. কিভাবে কিছু_ফাংশন সংজ্ঞায়িত করা হবে? প্রথম ক্ষেত্রে (কে, ভি), এটি কেবল দুটি পরামিতি নেয়? প্রথম চাবি তাহলে মান?
মেমো ২

হ্যাঁ, কেবল কলযোগ্য সুতরাং map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))- এটি আপনাকে দেবে [4]
বুরহান খালিদ

এটি সঠিক, তবে ব্যবহারের চেয়ে অজগরটি mapহ'ল একটি তালিকা বোধগম্যতা। [f(v) for k, v in d.iteritems() if substring in k]আমি মনে করি এটি অনেক বেশি পাঠযোগ্য এবং আরও দক্ষ।
ডেভিডম

@ মেমো এটি দুটি প্যারামিটার গ্রহণ করবে না, এটি দুটি উপাদান সহ একটি একক প্যারামিটার গ্রহণ করবে। রয়েছে starmap যা দুই আর্গুমেন্ট মধ্যে প্যাকমুক্ত ফেলবে না, যদিও এটি একটি অলস পুনরুক্তিকারীর আছে (আগেই executes, অর্থাত্ iterated করা আবশ্যক results = list(starmap(...))অথবা for result in starmap(...): ...)।
nmclean
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.