ফিল্টার ডিক শুধুমাত্র নির্দিষ্ট কী আছে?


496

আমার কাছে এমন একটি dictরয়েছে যা পুরো পুরো এন্ট্রি রাখে। আমি কেবলমাত্র তাদের কয়েকটিতে আগ্রহী। অন্য সবগুলি ছাঁটাই করার কোনও সহজ উপায় আছে?


কোন ধরণের কী (পূর্ণসংখ্যা? স্ট্রিং? তারিখ? স্বেচ্ছাসেবী বস্তু?) বলা সহজ এবং কোন কী কী আছে বা আউট আছে তা যাচাই করার জন্য একটি সরল (স্ট্রিং, রেজেক্স, তালিকার সদস্যতা, বা সংখ্যাগত বৈষম্য) পরীক্ষা আছে কিনা তা সহায়ক। অন্যথায় এটি নির্ধারণের জন্য আমাদের কোনও সালিশী ফাংশন (গুলি) কল করা দরকার to
smci

@ এসএমসি স্ট্রিং কীগুলি। এমন কি ভাববেন না যে আমার কাছে এমনটি ঘটেছিল যে আমি অন্য কিছু ব্যবহার করতে পারি; আমি এতক্ষণ জাতীয় এবং পিএইচপি কোডিং করে থাকেন ...
mpen

উত্তর:


654

একটি নতুন ডিক নির্মাণ:

dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }

অভিধান বোঝার ব্যবহার করে।

আপনি যদি এমন কোনও সংস্করণ ব্যবহার করেন যা এগুলির অভাব রয়েছে (যেমন পাইথন ২.6 এবং তার আগের), এটি তৈরি করুন dict((your_key, old_dict[your_key]) for ...) । এটা একই, যদিও কৃপণ।

নোট করুন যে, jnnnn এর সংস্করণের বিপরীতে old_dict, কোনও আকারের জন্য স্থিতিশীল পারফরম্যান্স রয়েছে (কেবলমাত্র আপনার_কিজের সংখ্যার উপর নির্ভর করে) । গতি এবং স্মৃতি উভয় ক্ষেত্রে। যেহেতু এটি একটি জেনারেটর এক্সপ্রেশন তাই এটি একবারে একটি আইটেম প্রসেস করে এবং এটি পুরানো_ডিক্টের সমস্ত আইটেমের মধ্যে দেখতে পায় না।

জায়গায় থাকা সমস্ত কিছু সরিয়ে ফেলা হচ্ছে:

unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]

8
"অভিধান বোধগম্যতা ব্যবহার করে, যদি আপনি এমন কোনও সংস্করণ ব্যবহার করেন যা এগুলির অভাব রয়েছে" == সংস্করণ <= 2.6
getekha

8
যদি ফাইলার কীগুলির মধ্যে একটি পুরানো_ডিক্টে উপস্থিত না থাকে তবে একটি কীরর ফেলে দেয়। আমি filter কে: ডি [কে] কে ফিল্টারে কে-ডি-ডি-এর জন্য পরামর্শ দিচ্ছি
পিটার গিবসন

1
@ পিটারজিবসন হ্যাঁ, এটি যদি প্রয়োজনীয়তার অংশ হয় তবে আপনার এটি সম্পর্কে কিছু করা দরকার । এটি নিঃশব্দে কীগুলি ফেলে দেওয়া, ডিফল্ট মান যুক্ত করা বা অন্য কিছু, আপনি যা করছেন তার উপর নির্ভর করে; প্রচুর ব্যবহারের কেস রয়েছে যেখানে আপনার দৃষ্টিভঙ্গি ভুল। এছাড়াও অনেকগুলি রয়েছে যেখানে একটি কী হারিয়েছে তা old_dictঅন্য কোথাও বাগ নির্দেশ করে এবং সেই ক্ষেত্রে আমি নিঃশব্দে ভুল ফলাফলের জন্য একটি ত্রুটি পছন্দ করি।

@ ডেলান, এছাড়াও "যদি কে ইন ডি" সংযোজন ডি বড় হলে আপনাকে ধীর করে দেয়, আমি কেবল ভেবেছিলাম এটি উল্লেখ করার মতো ছিল
পিটার গিবসন

7
@ পিটারজিবসন এটি করে না, অভিধানের অনুসন্ধান ও (1)।

130

সামান্য আরও মার্জিত ডিক বোধগম্যতা:

foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}

সম্মত। আমি এর অনুরূপ উত্তর যুক্ত করার বিষয়ে ভাবছিলাম। কৌতূহলের বাইরে যদিও, কেন {কে: ভি ফর কে, ডিক.াইটেম () ...} এর চেয়ে {কে: ডিক [কে] কে ডিক ইন কে ... performance পারফর্মেন্সের পার্থক্য রয়েছে?
হার্ট সিমহা

4
আমার নিজের প্রশ্নের উত্তর দিয়েছেন। Dict কে: ডিক [কে] ডিক ইন কে ...} প্রায় 20-25% দ্রুত, কমপক্ষে পাইথন ২.7..6 এ, 26 টি আইটেমের অভিধান (টাইমিট (..., সেটআপ = "ডি =) সহ {chr (x + 97): x + 1 রেঞ্জের রেঞ্জের জন্য (26)) ")), কতগুলি আইটেম ফিল্টার করা হচ্ছে তার উপর নির্ভর করে (স্বর কীগুলি ফিল্টার করার চেয়ে ব্যঞ্জন কীগুলি ফিল্টার আউট করা দ্রুত হয় কারণ আপনি সন্ধান করছেন) কম আইটেম)। আপনার অভিধানের আকারটি বাড়ার সাথে সাথে পারফরম্যান্সের পার্থক্য খুব কম গুরুত্বপূর্ণ হয়ে উঠতে পারে।
হার্ট সিংহা

5
আপনি mydict.iteritems()পরিবর্তে ব্যবহার করা হলে সম্ভবত একই পারফ হতে হবে। .items()অন্য তালিকা তৈরি করে।
প্যাট

64

পাইথন ২.6-এর একটি উদাহরণ এখানে রয়েছে:

>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}

ফিল্টারিং অংশটি ifস্টেটমেন্ট।

আপনি যদি খুব কয়েকটি কী ব্যবহার করতে চান তবে এই পদ্ধতিটি দেলানানের উত্তরের চেয়ে ধীর।


11
আমি সম্ভবত if key in ('x','y','z')আমি অনুমান ব্যবহার করি
এমপেন

আপনি যদি কোন চাবিগুলি ইতিমধ্যে জানতে চান তবে ডেলানানের উত্তরটি ব্যবহার করুন। যদি আপনার প্রতিটি আইফিকে স্টেটমেন্ট দিয়ে পরীক্ষা করতে হয় তবে রান্সফোর্ডের উত্তরটি ব্যবহার করুন।
jnnnnn

1
এই সমাধানটির আরও একটি সুবিধা রয়েছে। যদি কোনও ব্যয়বহুল ফাংশন কল থেকে অভিধানটি ফিরে আসে (অর্থাত্ a / old_dict একটি ফাংশন কল) এই সমাধানটি কেবল একবার ফাংশনটিকে কল করে। অত্যাবশ্যক পরিবেশে একটি ভেরিয়েবলে ফাংশন দ্বারা ফিরিয়ে নেওয়া অভিধান সংরক্ষণ করা কোনও বড় বিষয় নয় তবে কার্যকরী পরিবেশে (যেমন ল্যাম্বডায়) এটি মূল পর্যবেক্ষণ।
gae123


20

কোড 1:

dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
    if key % 2 == 0:
        d1[key] = value

কোড 2:

dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}

কোড 3:

dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}

কোড পারফরম্যান্সের সমস্ত পাইক সংখ্যা = 1000 ব্যবহার করে টাইমিট দিয়ে পরিমাপ করা হয় এবং কোডের প্রতিটি অংশের জন্য 1000 বার সংগ্রহ করা হয়।

এখানে চিত্র বর্ণনা লিখুন

অজগর 3.6 এর জন্য ফিল্টার ডিক কীগুলির তিনটি উপায়ে প্রায় একই রকমের পারফরম্যান্স। পাইথনের জন্য ২.7 কোড 3 কিছুটা দ্রুত is


শুধু কৌতূহল, আপনি কি পাইথন থেকে প্লট তৈরি করেছিলেন?
ব্যবহারকারী5359531

1
ggplot2 in r - tidyvers এর
keithpjolley

18

এই এক লাইনার ল্যাম্বডায় কাজ করা উচিত:

dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])

এখানে একটি উদাহরণ:

my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")

# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}

এটি আপনার মৌলিক তালিকার বোধগম্যতা যা আপনার ডিক কী (i x x) এর উপর পুনরাবৃত্তি করে এবং টিপল (কী, মান) জোড়গুলির একটি তালিকা আউটপুট দেয় যদি কী আপনার পছন্দসই কী তালিকায় থাকে (y)। একটি ডিক () পুরো জিনিসটি একটি ডিক অবজেক্ট হিসাবে আউটপুটে মোড়ানো করে।


একটি setব্যবহার করা উচিত wanted_keys, তবে অন্যথায় ভাল দেখাচ্ছে looks
এমপেন

আমার আসল অভিধানে যদি মানগুলির জায়গায় তালিকা থাকে তবে এটি আমাকে একটি ফাঁকা অভিধান দেয়। কোন workaround?
ফ্যাকফি

@ ফ্রান্সেসকো, আপনি একটি উদাহরণ দিতে পারেন? যদি আমি চালনা dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))করি:, এটি {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}উদ্দেশ্য হিসাবে ফিরে আসে ।
জিম 14

আমি এটি দিয়ে চেষ্টা করেছি: dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}এবং ফলাফলটি হয়েছিল {}, যা আমি একটি ফাঁকা ডিক হিসাবে ধরে নিয়েছিলাম।
ফ্যাকফি

একটি জিনিস, "ডিক" একটি সংরক্ষিত শব্দ তাই আপনার কোনও ডিকের নাম দেওয়ার জন্য এটি ব্যবহার করা উচিত নয়। আপনি কীগুলি টানতে চেষ্টা করেছিলেন তা কী ছিল? যদি আমি দৌড়ে যাই:, foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))আমি পেয়েছি: {'0': [1, 3], '2': [1, 4]}যা উদ্দেশ্য ফলাফল
জিম

14

আপনার আসল অভিধান origএবং আপনার আগ্রহী প্রবেশের সেট দেওয়া keys:

filtered = dict(zip(keys, [orig[k] for k in keys]))

যা দেলানানের উত্তরের মতো সুন্দর নয়, তবে প্রতিটি পাইথন সংস্করণের আগ্রহের কাজ করা উচিত। এটি keysআপনার মূল অভিধানে বিদ্যমান প্রতিটি উপাদানকে ভঙ্গুর করে তোলে ।


ঠিক আছে, এটি মূলত আমার ডিক বোঝার "টুপল জেনারেটর সংস্করণ" এর উত্সাহী সংস্করণ। অত্যন্ত সামঞ্জস্যপূর্ণ, যদিও জেনারেটর এক্সপ্রেশনগুলি 2.4, বসন্ত 2005-এ চালু হয়েছিল - গুরুত্ব সহকারে, কেউ কি এখনও এটি ব্যবহার করছে?

1
আমি একমত নই; ২.৩ এর আসলে আর অস্তিত্ব থাকা উচিত নয়। যাইহোক, ২.৩ ব্যবহারের পুরানো জরিপ হিসাবে: moinmo.in/PollAboutRequiringPython24 সংক্ষিপ্ত সংস্করণ: আরএইচইল 4, এসইএলএস 9, ওএস এক্স 10.4 এর সাথে পাঠানো হয়েছে
কাই

7

দেলানান কর্তৃক গৃহীত উত্তরের ভিত্তিতে।

যদি আপনার একটি চাওয়া চাবি পুরানো_ডিকেটে না থাকে? ডেলানান সলিউশনটি আপনি ধরতে পারেন এমন কী-ইরর ব্যতিক্রম নিক্ষেপ করবে। আপনার যদি এটি প্রয়োজন না হয় তবে আপনি চান:

  1. কেবলমাত্র এমন কীগুলি অন্তর্ভুক্ত করুন যা পুরাতন_দিক্ট এবং আপনার পছন্দসই_কিজের সেট উভয়ই উপস্থিত থাকে।

    old_dict = {'name':"Foobar", 'baz':42}
    wanted_keys = ['name', 'age']
    new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
    
    >>> new_dict
    {'name': 'Foobar'}
  2. পুরানো_ডিক্টে সেট না থাকা কীগুলির জন্য একটি ডিফল্ট মান রয়েছে।

    default = None
    new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
    
    >>> new_dict
    {'age': None, 'name': 'Foobar'}

আপনিও করতে পারেন{k: old_dict.get(k, default) for k in ...}
মোবার্গ

6

এই ফাংশনটি কৌশলটি করবে:

def include_keys(dictionary, keys):
    """Filters a dict by only including certain keys."""
    key_set = set(keys) & set(dictionary.keys())
    return {key: dictionary[key] for key in key_set}

ডেলাননের সংস্করণটির মতোই এটিও অভিধান বোঝা ব্যবহার করে এবং বড় অভিধানগুলির জন্য স্থিতিশীল পারফরম্যান্স থাকে (কেবলমাত্র আপনি অনুমোদিত কীগুলির সংখ্যার উপর নির্ভরশীল, অভিধানের কীগুলির মোট সংখ্যা নয়)।

এবং ঠিক মাইগান এর সংস্করণের মতোই এটির সাহায্যে আপনার কীগুলির তালিকাটি কীগুলিতে অন্তর্ভুক্ত থাকতে পারে যা অভিধানে বিদ্যমান নেই।

এবং বোনাস হিসাবে, এখানে বিপরীতটি রয়েছে, যেখানে আপনি মূল কয়েকটি কী বাদ দিয়ে একটি অভিধান তৈরি করতে পারেন:

def exclude_keys(dictionary, keys):
    """Filters a dict by excluding certain keys."""
    key_set = set(dictionary.keys()) - set(keys)
    return {key: dictionary[key] for key in key_set}

মনে রাখবেন যে ডেলানানের সংস্করণটির বিপরীতে, অপারেশনটি স্থানে করা হয় না, তাই পারফরম্যান্স অভিধানের কী সংখ্যার সাথে সম্পর্কিত। যাইহোক, এর সুবিধাটি হ'ল ফাংশনটি প্রদত্ত অভিধানটি সংশোধন করবে না।

সম্পাদনা: ডিক থেকে কিছু কী বাদ না দেওয়ার জন্য একটি পৃথক ফাংশন যুক্ত করা হয়েছে।


keysকোনও সেট পুনরায় গ্রহণযোগ্য , যেমন সেট সেট গ্রহণ করে তার মতো আপনার অনুমতি দেওয়া উচিত accep
এমপেন

আহ, ভাল কল, এটি নির্দেশ করার জন্য ধন্যবাদ। আমি সেই আপডেট করব।
রায়ান

আমি ভাবছি যদি আপনি দুটি ফাংশন দিয়ে ভাল হন। আপনি 10 জন জিজ্ঞাসা যদি "না invertযে পরোক্ষভাবে keysযুক্তি রাখা হয়, বা যে keysযুক্তি প্রত্যাখ্যাত?", তাদের কত সম্মত হবে?
স্কেটনার্ড

আপডেট করা হয়েছে। আমার সম্পর্কে আপনি কী মনে করেন জানি।
রায়ান 21

যদি ইনপুট ডিকের মানগুলির জায়গায় তালিকা থাকে তবে এটি কাজ করছে না বলে মনে হচ্ছে। এই ক্ষেত্রে আপনি একটি অকার্যকর ডিক পাবেন। কোন workaround?
ফ্যাকফি

4

আমরা যদি নির্বাচিত কীগুলি মুছে দিয়ে একটি নতুন অভিধান করতে চাই, আমরা অভিধান বোঝার ব্যবহার করতে পারি
উদাহরণস্বরূপ:

d = {
'a' : 1,
'b' : 2,
'c' : 3
}
x = {key:d[key] for key in d.keys() - {'c', 'e'}} # Python 3
y = {key:d[key] for key in set(d.keys()) - {'c', 'e'}} # Python 2.*
# x is {'a': 1, 'b': 2}
# y is {'a': 1, 'b': 2}

ঝরঝরে। পাইথন 3 এ কেবলমাত্র কাজ করে Py পাইথন 2 বলেছেন "প্রকারেরর: অসমর্থিত অপরেন্দ্র প্রকারের জন্য -: 'তালিকা' এবং 'সেট'"
এমপেন

পাইথন ২-এর জন্য সেট (d.keys ()) যুক্ত হয়েছে I
শ্রীবাস্তব

2

অন্য বিকল্প:

content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())

তবে আপনি একটি list(পাইথন 2) বা একটি পুনরুদ্ধারকারী (পাইথন 3) পেয়েছেন filter(), এটি নয় dict


মোড়ানো filteredমধ্যে dictএবং আপনার অভিধান ফিরে পেতে!
সিএমসিডিগ্রাগনকাই

1

সংক্ষিপ্ত রূপ:

[s.pop(k) for k in list(s.keys()) if k not in keep]

সংক্ষিপ্ততা বজায় রাখার জন্য বেশিরভাগ উত্তর হিসাবে পরামর্শ হিসাবে আমাদের একটি ডুপ্লিকেট অবজেক্ট তৈরি করতে হবে এটি হোক listবা একটি dict। এটি একটি ছোঁড়াছুড়ি তৈরি করে listতবে মূলগুলি কীগুলি মুছে দেয় dict


0

delএকটি লাইনারে ব্যবহার করে এখানে আরও একটি সহজ পদ্ধতি :

for key in e_keys: del your_dict[key]

e_keysবাদ দেওয়া হবে কীগুলির তালিকা। এটি আপনাকে নতুন দেওয়ার পরিবর্তে আপনার ডিককে আপডেট করবে।

যদি আপনি একটি নতুন আউটপুট ডিক চান, তবে মুছে ফেলার আগে ডকের একটি অনুলিপি তৈরি করুন:

new_dict = your_dict.copy()           #Making copy of dict

for key in e_keys: del new_dict[key]

0

আপনি ব্যবহার করতে পারেন python-benedict , এটি একটি ডিক সাবক্লাস।

স্থাপন: pip install python-benedict

from benedict import benedict

dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])

এটি গিটহাবের ওপেন সোর্স: https://github.com/fabiocaccamo/python-benedict


দাবি অস্বীকার: আমি এই গ্রন্থাগারের লেখক।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.