একটি অভিধান থেকে নিরাপদে একাধিক কী সরিয়ে ফেলা হচ্ছে


127

আমি আমার অভিধান থেকে একটি কী, 'কী' অপসারণ করতে জানি d, নিরাপদে আপনি:

if d.has_key('key'):
    del d['key']

তবে, অভিধান থেকে আমার একাধিক এন্ট্রি নিরাপদে সরিয়ে ফেলতে হবে। আমি একটি টিপল এন্ট্রি সংজ্ঞায়িত করার কথা ভাবছিলাম যেহেতু আমার একাধিকবার এটি করা দরকার।

entitiesToREmove = ('a', 'b', 'c')
for x in entitiesToRemove:
    if d.has_key(x):
        del d[x]

যাইহোক, আমি ভাবছিলাম যে এটি করার কোনও স্মার্ট উপায় আছে কিনা?


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

1
@ ম্যাটবর্নস্কির উত্তরটি আরও প্রচলিত এবং সাফল্যজনক বলে মনে হচ্ছে।
আইওনিস ফিলিপিসিস

2
Stackoverflow কথা বলেননি |: key in dআরো Pythonic চেয়ে d.has_key(key) stackoverflow.com/questions/1323410/has-key-or-in
মাইকেল Scheper

আপনি যদি কিছুটা স্মৃতি রেখে দিতে পারেন তবে আপনি এটি করতে পারেন for x in set(d) & entities_to_remove: del d[x]। এটি সম্ভবত entities_to_remove"বৃহত্তর" হলে আরও কার্যকর হবে ।
ডিলানইং

উত্তর:


56

কেন এটি পছন্দ হয় না:

entries = ('a', 'b', 'c')
the_dict = {'b': 'foo'}

def entries_to_remove(entries, the_dict):
    for key in entries:
        if key in the_dict:
            del the_dict[key]

ডেট.পপ () ব্যবহার করে ম্যাটথোর্নস্কি একটি আরও কমপ্যাক্ট সংস্করণ সরবরাহ করেছিলেন


14
অনুসন্ধান ইঞ্জিন থেকে আগত লোকদের জন্য এটি যুক্ত করা হচ্ছে। কীগুলি জানা থাকলে (যখন সুরক্ষা কোনও সমস্যা নয়), একাধিক কী এর মতো একটি লাইনে মুছতে পারেdel dict['key1'], dict['key2'], dict['key3']
তীর্থ 30

আপনি মুছে ফেলছেন কীগুলির সংখ্যার উপর নির্ভর করে, পরীক্ষাটি ব্যবহার for key in set(the_dict) & entries:এবং বাইপাস করা আরও দক্ষ might key in dict
ডিলানইং

235
d = {'some':'data'}
entriesToRemove = ('any', 'iterable')
for k in entriesToRemove:
    d.pop(k, None)

37
এই. এটি চতুর পাইথনিস্তার পছন্দ। dict.pop()মূল অস্তিত্ব পরীক্ষার প্রয়োজনীয়তা দূর করে। চমৎকার।
সিসিল কারি

4
এটির জন্য মূল্যবান, আমি মনে করি .pop()খারাপ এবং অপ্রচলিত, এবং এটির চেয়ে গ্রহণযোগ্য উত্তরটি পছন্দ করবে।
আর্ন

5
এক বিস্ময়কর ব্যক্তি এটি দ্বারা উদ্বেগযুক্ত প্রদর্শিত হবে: আমি ব্যক্তিগতভাবে অস্তিত্বের জন্য যাচাই করার জন্য অতিরিক্ত রেখাকে আপত্তি করি না এবং পপ () সম্পর্কে আপনি ইতিমধ্যে অবগত না হলে এটি উল্লেখযোগ্যভাবে আরও পঠনযোগ্য। অন্যদিকে আপনি যদি কোনও বোধগম্যতা বা ইনলাইন ল্যাম্বডায় এটি করার চেষ্টা করছিলেন তবে এই কৌশলটি বড় সহায়ক হতে পারে। আমি এও বলব যে আমার মতে, লোকেরা যেখানে রয়েছে তাদের সাথে দেখা করা এটি গুরুত্বপূর্ণ। আমি নিশ্চিত নই যে "খারাপ এবং অযৌক্তিক" এই উত্তরগুলি পড়ছে এমন লোকদের তারা যে ব্যবহারিক গাইডেন্স সন্ধান করছে তা দিচ্ছে।
mattbornski

5
একটা বিশেষ করে হয় ভাল এটি ব্যবহার করার কারণ। অতিরিক্ত লাইন যুক্ত করার সাথে "পাঠযোগ্যতা" বা "স্পষ্টতা" উন্নতি হতে পারে, এটি অভিধানে একটি অতিরিক্ত অনুসন্ধান যুক্ত করে। এই পদ্ধতিটি হ'ল করণের সমতুল্য setdefault। যদি সঠিকভাবে প্রয়োগ করা হয় (এবং আমি নিশ্চিত যে এটি) তবে এটি কেবল dictদুটি পরিবর্তে হ্যাশ-মানচিত্রে একটি অনুসন্ধান করে ।
ম্যাড পদার্থবিদ

2
ব্যক্তিগতভাবে আমি প্রথমে নির্ভুলতা এবং রক্ষণাবেক্ষণের সাথে উদ্বিগ্ন হব এবং গতি কেবলমাত্র যদি এটি অপর্যাপ্তভাবে দ্রুত প্রমাণিত হয়। অ্যাপ্লিকেশন স্তরের জুম বাড়ানোর সময় এই ক্রিয়াকলাপগুলির মধ্যে গতির পার্থক্য তুচ্ছ হতে চলেছে। এটির ক্ষেত্রে এটি দ্রুত হতে পারে তবে আমি প্রত্যাশা করি যে সত্যিকারের বিশ্ব ব্যবহারের ক্ষেত্রে আপনি খেয়াল রাখবেন না এবং যত্নও করবেন না এবং আপনি যদি খেয়াল ও যত্ন নেন তবে আপনাকে পাইথনের চেয়ে আরও বেশি পারফরম্যান্ট কিছুতে পুনর্লিখনের পরিবেশ দেওয়া হবে।
mattbornski

89

ডিক্ট সমঝোতা ব্যবহার করে

final_dict = {key: t[key] for key in t if key not in [key1, key2]}

যেখানে key1 এবং কী 2 সরানো হবে।

নীচের উদাহরণে, "বি" এবং "সি" কীগুলি সরানো হবে এবং এটি একটি কী তালিকায় রাখা হবে।

>>> a
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>> keys = ["b", "c"]
>>> print {key: a[key] for key in a if key not in keys}
{'a': 1, 'd': 4}
>>> 

4
নতুন অভিধান? তালিকা বোঝার? আপনার জিজ্ঞাসা করা ব্যক্তির উত্তরটি সামঞ্জস্য করা উচিত;)
গ্লাস্লোস

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

14
পাঠযোগ্যতার খাতিরে, আমি প্রস্তাব দিচ্ছি {k: v for k, v in t.items () k না থাকলে [কী 1, কী 2]}
ফ্রেডেরিক বাজিন

8
কীগুলির তালিকাগুলি যখন খুব বড় হয় তত সার্চ করার সময় এর কার্য সম্পাদনের সমস্যাও থাকে O(n)। পুরো অপারেশন O(mn), যেখানে mঅভি কি সংখ্যা এবং nতালিকায় কী সংখ্যা। আমি {key1, key2}পরিবর্তে একটি সেট ব্যবহার করার পরামর্শ দিচ্ছি , যদি সম্ভব হয়।
ldavid

4
আপালালাকে: আপনি আমাকে বুঝতে সাহায্য করতে পারেন কেন একটি পারফরম্যান্স হিট হয়েছে?
শন

21

একটি সমাধান ব্যবহার mapএবং filterফাংশন হয়

অজগর 2

d={"a":1,"b":2,"c":3}
l=("a","b","d")
map(d.__delitem__, filter(d.__contains__,l))
print(d)

অজগর 3

d={"a":1,"b":2,"c":3}
l=("a","b","d")
list(map(d.__delitem__, filter(d.__contains__,l)))
print(d)

তুমি পাও:

{'c': 3}

এটি অজগর 3.4 নিয়ে আমার পক্ষে কাজ করে না:>>> d={"a":1,"b":2,"c":3} >>> l=("a","b","d") >>> map(d.__delitem__, filter(d.__contains__,l)) <map object at 0x10579b9e8> >>> print(d) {'a': 1, 'b': 2, 'c': 3}
রিসাদিনহা

@ রিসাদিনহা list(map(d.__delitem__,filter(d.__contains__,l))).... অজগর 3..৪-এ মানচিত্রের ফাংশনটি একটি পুনরাবৃত্তিকে ফিরিয়ে দেয়
জোসে রিকার্ডো বুস্টোস এম।

4
বা deque(map(...), maxlen=0)কোনও মানগুলির তালিকা তৈরি করা এড়াতে; প্রথম আমদানিfrom collections import deque
জেসন

19

আপনি যে কীগুলি অপসারণ করছেন সেগুলির জন্য যদি মানগুলি পুনরুদ্ধার করার প্রয়োজনও হয় তবে এটি করার এটি বেশ ভাল উপায় হবে:

valuesRemoved = [d.pop(k, None) for k in entitiesToRemove]

আপনি অবশ্যই এটি থেকে কীগুলি অপসারণের জন্য এখনও করতে পারেন dতবে আপনি অযথা তালিকার বোধগম্যতার সাথে মানগুলির তালিকা তৈরি করবেন। কেবল ফাংশনটির পার্শ্ব প্রতিক্রিয়ার জন্য একটি তালিকা বোধগম্যতা ব্যবহার করাও কিছুটা অস্পষ্ট।


3
অথবা আপনি মুছে ফেলা এনট্রিগুলিকে অভিধান হিসাবে রাখতে চান :valuesRemoved = dict((k, d.pop(k, None)) for k in entitiesToRemove) ইত্যাদি so
kindall

আপনি ভেরিয়েবলের অ্যাসাইনমেন্টটি ছেড়ে দিতে পারেন। এই বা সেভাবে এটি সংক্ষিপ্ত এবং সর্বাধিক পাইথোনিক সমাধান এবং মূল উত্তর উত্তর আইএমএইচও হিসাবে চিহ্নিত করা উচিত।
জেরহার্ড হেইজার

12

সঙ্গে একটি সমাধান পাওয়া popএবংmap

d = {'a': 'valueA', 'b': 'valueB', 'c': 'valueC', 'd': 'valueD'}
keys = ['a', 'b', 'c']
list(map(d.pop, keys))
print(d)

এর ফলাফল:

{'d': 'valueD'}

আমি এই প্রশ্নের উত্তর এত দেরিতে দিয়েছি কারণ আমি মনে করি যে কেউ যদি এটির সন্ধান করে তবে এটি ভবিষ্যতে সহায়তা করবে। এবং এটি সাহায্য করতে পারে।

হালনাগাদ

উপরের কোডটি যদি একটি কীটি ডিকটিতে উপস্থিত না থাকে তবে ত্রুটি ছুঁড়ে ফেলবে।

DICTIONARY = {'a': 'valueA', 'b': 'valueB', 'c': 'valueC', 'd': 'valueD'}
keys = ['a', 'l', 'c']

def remove_keys(key):
    try:
        DICTIONARY.pop(key, None)
    except:
        pass  # or do any action

list(map(remove_key, keys))
print(DICTIONARY)

আউটপুট:

DICTIONARY = {'b': 'valueB', 'd': 'valueD'}

1
যদি কোনও কী keysউপস্থিত না থাকে তবে এই উত্তরটি একটি ব্যতিক্রম ছুঁড়ে dফেলবে - আপনাকে প্রথমে এটি ফিল্টার করতে হবে।
ingofreyer

@ingofreyer ব্যতিক্রম পরিচালনার জন্য কোড আপডেট করেছে। এই সমস্যাটি সন্ধানের জন্য ধন্যবাদ। আমি এখন এটি কাজ করবে বলে মনে করি। :)
শুভম শ্রীবাস্তব

ধন্যবাদ,
এটির

মানচিত্র ব্যবহারের উপ-পণ্য হিসাবে একটি তালিকা তৈরি করা এটিকে বেশ ধীর করে দেয়, এটির উপরে লুপ করা ভাল।
চার্লি ক্লার্ক

4

বিদ্যমান উত্তরগুলির সাথে আমার কোনও সমস্যা নেই তবে আমি এই সমাধানটি না পেয়ে অবাক হয়েছি:

keys_to_remove = ['a', 'b', 'c']
my_dict = {k: v for k, v in zip("a b c d e f g".split(' '), [0, 1, 2, 3, 4, 5, 6])}

for k in keys_to_remove:
    try:
        del my_dict[k]
    except KeyError:
        pass

assert my_dict == {'d': 3, 'e': 4, 'f': 5, 'g': 6}

দ্রষ্টব্য: আমি এখান থেকে আসা এই প্রশ্ন জুড়ে হোঁচট খেয়েছি । এবং আমার উত্তর এই উত্তর সম্পর্কিত ।


3

কেন না:

entriestoremove = (2,5,1)
for e in entriestoremove:
    if d.has_key(e):
        del d[e]

"স্মার্ট উপায়" দ্বারা আপনি কী বোঝাতে চেয়েছেন তা আমি জানি না। অভিধানের বোধগম্যতার সাথে অবশ্যই অন্যান্য উপায় রয়েছে:

entriestoremove = (2,5,1)
newdict = {x for x in d if x not in entriestoremove}

2

সঙ্গতিপূর্ণভাবে

import functools

#: not key(c) in d
d = {"a": "avalue", "b": "bvalue", "d": "dvalue"}

entitiesToREmove = ('a', 'b', 'c')

#: python2
map(lambda x: functools.partial(d.pop, x, None)(), entitiesToREmove)

#: python3

list(map(lambda x: functools.partial(d.pop, x, None)(), entitiesToREmove))

print(d)
# output: {'d': 'dvalue'}

2

সিপাইথন 3 এর জন্য কিছু সময় পরীক্ষা করে দেখায় যে লুপের জন্য একটি সহজতম দ্রুততম উপায় এবং এটি বেশ পঠনযোগ্য। কোনও ফাংশনে যোগ করার কারণে খুব বেশি ওভারহেডের কারণ হয় না:

সময়কালীন ফলাফল (10 কে পুনরাবৃত্তি):

  • all(x.pop(v) for v in r) # 0.85
  • all(map(x.pop, r)) # 0.60
  • list(map(x.pop, r)) # 0.70
  • all(map(x.__delitem__, r)) # 0.44
  • del_all(x, r) # 0.40
  • <inline for loop>(x, r) # 0.35
def del_all(mapping, to_remove):
      """Remove list of elements from mapping."""
      for key in to_remove:
          del mapping[key]

ছোট পুনরাবৃত্তির জন্য, ফাংশন কলের ওভারহেডের কারণে, 'ইনলাইন' করা কিছুটা দ্রুত ছিল। তবে del_allলিন্ট-নিরাপদ, পুনরায় ব্যবহারযোগ্য এবং সমস্ত অজগর বোধগম্যতা এবং ম্যাপিংয়ের নির্মাণগুলির চেয়ে দ্রুত।


0

আমি মনে করি যে কীগুলি সেট হিসাবে বিবেচনা করা যেতে পারে তা ব্যবহার করা যদি আপনি অজগর 3 তে থাকেন তবে সর্বোত্তম উপায়:

def remove_keys(d, keys):
    to_remove = set(keys)
    filtered_keys = d.keys() - to_remove
    filtered_values = map(d.get, filtered_keys)
    return dict(zip(filtered_keys, filtered_values))

উদাহরণ:

>>> remove_keys({'k1': 1, 'k3': 3}, ['k1', 'k2'])
{'k3': 3}

0

অভিধানের জন্য সেট পদ্ধতির (এবং পাইথন ৩.৯-এর সাথে আমরা যে অপরিষ্কার জগাখিচুড়ি করছি না তা নয়) পুরো সমর্থনটি পেয়ে ভাল লাগবে যাতে আপনি কীগুলির সেটগুলি কেবল "মুছে ফেলতে" পারেন। যাইহোক, যতক্ষণ না এটি হয় না, এবং আপনার কাছে সম্ভাব্য সংখ্যক কীগুলি মুছে ফেলার জন্য একটি বৃহত অভিধান রয়েছে, আপনি পারফরম্যান্স সম্পর্কে জানতে চাইতে পারেন। সুতরাং, আমি এমন কিছু কোড তৈরি করেছি যা অর্থপূর্ণ তুলনার জন্য যথেষ্ট বড় কিছু তৈরি করে: একটি 100,000 x 1000 ম্যাট্রিক্স, সুতরাং মোট 10,000,00 আইটেম।

from itertools import product
from time import perf_counter

# make a complete worksheet 100000 * 1000
start = perf_counter()
prod = product(range(1, 100000), range(1, 1000))
cells = {(x,y):x for x,y in prod}
print(len(cells))

print(f"Create time {perf_counter()-start:.2f}s")
clock = perf_counter()
# remove everything above row 50,000

keys = product(range(50000, 100000), range(1, 100))

# for x,y in keys:
#     del cells[x, y]

for n in map(cells.pop, keys):
    pass

print(len(cells))
stop = perf_counter()
print(f"Removal time {stop-clock:.2f}s")

10 মিলিয়ন আইটেম বা আরও কিছু কিছু সেটিংসে অস্বাভাবিক নয়। আমার স্থানীয় মেশিনে দুটি পদ্ধতির তুলনা করে আমি ব্যবহার করার সময় সামান্য উন্নতি দেখতে পাচ্ছি mapএবং popসম্ভবত কম ফাংশন কল করার কারণে, তবে উভয়ই আমার মেশিনে প্রায় 2.5 শতাংশ সময় নেয়। তবে প্রথম স্থানে (55 এর দশকে) বা লুপের মধ্যে থাকা চেক সহ অভিধান তৈরি করতে প্রয়োজনীয় সময়ের তুলনায় এই প্লেসগুলি। যদি এটি সম্ভবত হয় তবে এমন একটি সেট তৈরি করা সেরা যা অভিধান কী এবং আপনার ফিল্টারের ছেদ হয় is

keys = cells.keys() & keys

সংক্ষেপে: delইতিমধ্যে ভারী অনুকূলিতকরণ করা হয়েছে, সুতরাং এটি ব্যবহারের বিষয়ে চিন্তা করবেন না।


-1

আমি এই আলোচনায় দেরি করছি তবে অন্য কারও জন্য। সমাধানগুলির জন্য কীগুলির একটি তালিকা তৈরি করা হতে পারে।

k = ['a','b','c','d']

তারপরে কীগুলির উপর পুনরাবৃত্তি করতে একটি তালিকা বোধগমিতে বা লুপের জন্য পপ () ব্যবহার করুন এবং একই সময়ে একটিকে পপ করুন।

new_dictionary = [dictionary.pop(x, 'n/a') for x in k]

'এন / এ' ক্ষেত্রে কীটি বিদ্যমান না থাকলে ডিফল্ট মানটি ফেরত নেওয়া দরকার be


8
new_dictionaryতালিকার মতো ভয়ঙ্কর অনেক দেখাচ্ছে;)
ডিলান ইউং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.