কোনও অভিধানে একটি প্রদত্ত কী ইতিমধ্যে উপস্থিত রয়েছে কিনা তা পরীক্ষা করে এটি বাড়িয়ে দিন


294

একটি অভিধান দেওয়া, আমি কীভাবে এটি আবিষ্কার করতে পারি যে সেই অভিধানে প্রদত্ত কীটি ইতিমধ্যে অ-মান মান সেট করা আছে কিনা?

অর্থাৎ আমি এটি করতে চাই:

my_dict = {}

if (my_dict[key] != None):
  my_dict[key] = 1
else:
  my_dict[key] += 1

অর্থাৎ, আমি যদি ইতিমধ্যে সেখানে থাকে তবে মান বাড়িয়ে দিতে চাই, বা অন্যথায় এটি 1 এ সেট করে।


11
ছোট কোড নিতপিক: কোডটি ইতিমধ্যে কিছু আছে যদি my_dict [কী] 1 তে সেট করে, এবং যদি না থাকে তবে এটি বৃদ্ধি করে। আমার মনে হয় আপনি == চান, না! =।
কোয়ান্টামফুল

উত্তর:


331

আপনি খুঁজছেন collections.defaultdict(পাইথন 2.5+ এর জন্য উপলব্ধ)। এই

from collections import defaultdict

my_dict = defaultdict(int)
my_dict[key] += 1

আপনি যা চান তা করবে

নিয়মিত পাইথন জন্য dictS, যদি সেখানে একটি প্রদত্ত কী-এর জন্য কোনো মূল্য থাকে, তবে আপনি হবে না পেতে Noneযখন অভি অ্যাক্সেস - একটি KeyErrorউত্থাপিত করা হবে না। সুতরাং আপনি যদি dictনিজের কোডের পরিবর্তে কোনও নিয়মিত ব্যবহার করতে চান তবে আপনি ব্যবহার করতে পারেন

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1

8
তার উদাহরণ অনুসারে, এটি "ডিফল্টডিক্ট (ল্যাম্বডা: 0)" সেট করার জন্য যথেষ্ট এবং "যদি" ধারাটি সম্পূর্ণ এড়িয়ে যায়।
ডিস্টান

এটি কাজ করে তবে কীগুলি এবং মানগুলিকে বিভ্রান্ত করে (এটি পড়তে কিছুটা বিজোড় করে তোলে)। 'কিছু_মূল্য' 'কিছু_কী' হওয়া উচিত
মাইমেকচানা

@ নাইলার: স্থির, ধন্যবাদ আমি প্রথমে 'কিছু_মূল্য' ব্যবহার করেছি যেহেতু এটির প্রশ্নের পরিবর্তনশীল নাম, তবে আমি এখনই এটি পরিষ্কার হতে সম্মত।
ডিএফ।

20
... বা নিয়মিত জন্য dict, আপনি করতে পারেন my_dict[key] = my_dict.get(key, 0) + 1
minmaxavg

নেস্টেড অভিধানগুলিতে এটি কীভাবে প্রসারিত করা যায়? ডিক্ট [কী 1] [কী 2] + = 1?
পাবলো রুইজ রুইজ

300

আমি কোডের এক লাইনে এটি করতে পছন্দ করি।

আমার_ডিক্ট =}

আমার_ডিক্ট [কিছু_কি] = আমার_ডিক্ট.জেট (কিছু_কি, 0) + 1

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


1
@ অ্যান্ড্রুউইলকিনসন আমার খারাপ আপনার উত্তরটি আমার মতো করে পড়া হয়নি।
মাসআরস

59

আমি ব্যক্তিগতভাবে ব্যবহার পছন্দ করি setdefault()

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1

setdefaultঅসাধারণ. এটির জন্য কোনওটির জন্য ইতিমধ্যে সেট করা থাকলে মান পরিবর্তন করে না some_key। উদাহরণস্বরূপ, d={1:2}; d.setdefault(1, 0)এর মানটি বিরক্ত করে না d[1]
wsaleem

49

তার key in dictজন্য আপনার প্রতিমা দরকার ।

if key in my_dict and not (my_dict[key] is None):
  # do something
else:
  # do something else

তবে আপনার সম্ভবত সম্ভবত ব্যবহার defaultdict(ডিএফ প্রস্তাবিত) হিসাবে বিবেচনা করা উচিত ।


1
দয়া করে নোট করুন যে কমপক্ষে ২.6-তে has_key () ডি-তে কী এর পক্ষে চিত্রিত হয়েছে। আমার মনে হয় এটি 2.5 এও ছিল।
ডেভিড লক

নোট করুন যে কেউ লিখতে পারেন my_dict[key] is not None, যা পরিষ্কার (
IMHO

@brandizzi - একমত,if key in my_dict and my_dict[key]:
রব গ্রান্ট

18

" সেই ডিকের কোনও প্রদত্ত সূচকটি ইতিমধ্যে অ-নয় মান হিসাবে সেট করা আছে কিনা আমি কীভাবে জানতে পারি", আমি এটিকে পছন্দ করব:

try:
  nonNone = my_dict[key] is not None
except KeyError:
  nonNone = False

এটি ইএএফপি এর ইতিমধ্যে অনুরোধ করা ধারণার সাথে সামঞ্জস্য করে (ক্ষমা চাওয়ার পরে অনুমতি চেয়ে সহজ)। এটি অভিধানে ডুপ্লিকেট কী অনুসন্ধানটি এড়িয়ে যায় কারণ এটি চেহারা key in my_dict and my_dict[key] is not Noneব্যয়বহুল হলে আকর্ষণীয়।

আপনি যে প্রকৃত সমস্যাটি উত্থাপন করেছেন তার জন্য, যেমন যদি এটি উপস্থিত থাকে তবে কোনও পূর্বে বৃদ্ধি করা বা অন্যথায় এটি একটি ডিফল্ট মান হিসাবে সেট করা হয়, আমিও সুপারিশ করি

my_dict[key] = my_dict.get(key, default) + 1

যেমনটি অ্যান্ড্রু উইলকিনসনের উত্তরে।

আপনি যদি আপনার অভিধানে সংশোধনযোগ্য অবজেক্টগুলি সঞ্চয় করছেন তবে তৃতীয় সমাধান রয়েছে solution এটির জন্য একটি সাধারণ উদাহরণ একটি মাল্টিম্যাপ , যেখানে আপনি আপনার কীগুলির জন্য উপাদানগুলির একটি তালিকা সঞ্চয় করেন। সেক্ষেত্রে, আপনি ব্যবহার করতে পারেন:

my_dict.setdefault(key, []).append(item)

অভিধানে যদি কীটির কোনও মান বিদ্যমান না থাকে তবে সেটডেফল্ট পদ্ধতি সেটডেফল্টের দ্বিতীয় প্যারামিটারে সেট করে। এটি ঠিক একটি স্ট্যান্ডার্ড মাই_ডিক্ট [কী] এর মতো আচরণ করে, কীটির মান (যা নতুন সেট করা মান হতে পারে) ফেরত দেয়।


পাইথোনিকটি আসলে (আমার মতো বহিরাগতের কাছে) কী বলে মনে হচ্ছে যে কোনও প্রশ্নের কমপক্ষে 3 টি বৈধ উত্তর রয়েছে :)
ডাভকা

@ ড্যাভকা: আচ্ছা, তিনটি ব্যবহারের ক্ষেত্রে প্রায় একইরকম, তবে ভিন্ন: ক) অভিধানে অ-নন উপাদান রয়েছে কিনা তা খুঁজে বের করুন খ) অভিধান থেকে একটি মান উদ্ধার করুন বা মান বিদ্যমান না থাকলে ডিফল্ট ব্যবহার করুন গ) অভিধান থেকে একটি মান পুনরুদ্ধার করুন এবং মানটি এখনও উপস্থিত না থাকলে একটি ডিফল্ট সঞ্চয় করুন।
এনডি।

আমি জানি :) এটি কোনও সমালোচনা নয়, আমি এই সত্য দ্বারা কেবল বিস্মিত
ডাভকা

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

1
@ মিশেলফ্রাইথ আমি পাইথনের ব্যতিক্রম ওভারহেডের জন্য একটি অভিশাপ অনুসন্ধান করেছি: স্ট্যাকওভারফ্লো / প্রশ্ন / 2522005/… এটি ধীর, তবে খুব বেশি নয়। মনে রাখবেন যে একটি ব্যতিক্রম নিক্ষেপের উচ্চ স্তরের ধারণাটি বিভিন্ন ভাষায় খুব আলাদাভাবে পরিচালনা করা হয় এবং আপনি পক্ষে এবং কৌশলগুলি সাধারণ করতে পারবেন না। সুতরাং "ব্যতিক্রমগুলির 10x ওভারহেড রয়েছে" জাভা জন্য সঠিক হতে পারে, এটি পাইথন (বা সুইফট বা অন্যদের) জন্য নয়।
এনডি।

13

সিগোল্ডবার্গের সাথে একমত আমি এটি কিভাবে করি:

try:
    dict[key] += 1
except KeyError:
    dict[key] = 1

সুতরাং হয় উপরের মতো এটি করুন, বা অন্যদের পরামর্শ মতো একটি ডিফল্ট ডিক ব্যবহার করুন। বিবৃতি যদি ব্যবহার করবেন না। এটি পাইথোনিক নয়।


8
বিবৃতি পাইথোনিক না হয় কিভাবে?
অ্যাডাম পার্কিন

2
আমি মনে করি এটি এমন একটি ক্ষেত্রে যেখানে পাইথনের ইএএফপি সবচেয়ে ভাল উপায় নয়। উপরের আপনার উদাহরণটিতে নকল কোড রয়েছে; একদিন যদি আমরা চাই +=2বা কি হয় -=1? আপনাকে দুটি লাইন পরিবর্তন করতে হবে মনে রাখতে হবে। এটি এখন একটি তুচ্ছ জিনিস মনে হতে পারে, তবে সেগুলি হ'ল নির্বোধ ছোট 'তুচ্ছ' বাগ যা আপনাকে কামড়ানোর জন্য ফিরে আসতে পারে।
ক্যাম জ্যাকসন

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

11

আপনি অনেক উত্তর থেকে দেখতে পাচ্ছেন, বেশ কয়েকটি সমাধান রয়েছে। এলবিওয়াইএল-এর একটি উদাহরণ (আপনি লাফানোর আগে দেখুন) এখনও বলা হয়নি, হ্যাশকি () পদ্ধতি:

my_dict = {}

def add (key):
    if my_dict.has_key(key):
        my_dict[key] += 1
    else:
        my_dict[key] = 1

if __name__ == '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict

6
has_key () 'ইন' অপারেটরের চেয়ে ধীর এবং কম পঠনযোগ্য।
আবলান

9
... এবং এটি পাইথন ২.6 এ
অবহেলা করা

7

আপনি যেভাবে এটি করার চেষ্টা করছেন তাকে LBYL বলা হয় (লাফানোর আগে দেখুন), যেহেতু আপনি নিজের মান বাড়ানোর চেষ্টা করার আগে শর্তাদি পরীক্ষা করছেন।

অন্য পদ্ধতির নাম হয় ইএএফপি (ক্ষমা চাওয়ার পরে অনুমতি চাইতে সহজ)। সেক্ষেত্রে আপনি কেবল অপারেশনটি (মান বাড়ানোর) চেষ্টা করবেন। যদি এটি ব্যর্থ হয়, আপনি ব্যতিক্রমটি ধরুন এবং মানটি 1 তে সেট করুন This এটি করার কিছুটা বেশি পাইথোনিক উপায় (আইএমও)।

http://mail.python.org/pipermail/python-list/2003-May/205182.html


5

কিছুটা দেরি হলেও এটি কাজ করা উচিত।

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1

বাহ, একটি জাভা প্রোগ্রামার হিসাবে, এটি একটি সুন্দর উন্মাদ-চেহারা নির্মাণ ruct এটি দেখতে অদ্ভুত অর্ডারযুক্ত টেরিনারি অপারেটরের মতো দেখাচ্ছে?
forresthopkinsa

5

এটি সরাসরি প্রশ্নের উত্তর দিচ্ছে না, তবে আমার কাছে মনে হচ্ছে আপনি সংগ্রহের কার্যকারিতা চাইতে পারেন oun কাউন্টার

from collections import Counter

to_count = ["foo", "foo", "bar", "baz", "foo", "bar"]

count = Counter(to_count)

print(count)

print("acts just like the desired dictionary:")
print("bar occurs {} times".format(count["bar"]))

print("any item that does not occur in the list is set to 0:")
print("dog occurs {} times".format(count["dog"]))

print("can iterate over items from most frequent to least:")
for item, times in count.most_common():
    print("{} occurs {} times".format(item, times))

ফলাফল আউটপুট

Counter({'foo': 3, 'bar': 2, 'baz': 1})
acts just like the desired dictionary:
bar occurs 2 times
any item that does not occur in the list is set to 0:
dog occurs 0 times
can iterate over items from most frequent to least:
foo occurs 3 times
bar occurs 2 times
baz occurs 1 times

কাউন্টার ঠিক defaultdict(int)কিছু অতিরিক্ত কার্যকারিতার সাথে কাজ করে তাই এটি পূর্ণাঙ্গভাবে কাজ করবে যখন এককভাবে পূর্ণসংখ্যার সাথে ডিল করার সময় তবে আপনি কোনও প্রাসঙ্গিক আচরণ দেখান না।
তাদগ ম্যাকডোনাল্ড-জেনসেন

4

এই সমস্যাটি সমাধানের জন্য আমি সম্প্রতি একটি লাইনার নিয়ে এসেছি। এটি সেটডফল্ট অভিধান পদ্ধতির উপর ভিত্তি করে :

my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1

0

আমি এটি সন্ধান করছিলাম, ওয়েবে এটি খুঁজে পেলাম না তারপরে চেষ্টা / ত্রুটির সাথে আমার ভাগ্য চেষ্টা করে খুঁজে পেয়েছি

my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1

1
আপনার __contains__কোনও প্রোডাকশন কোড ব্যবহার করা উচিত নয় । BTW। __contains__ব্যবহার হিসাবে একই is
ব্যবহারকারী 1767754

1
my_dict.__contains__(some_key)সমতুল্য some_key in my_dict, ওভারলোড inঅপারেটরের জন্য নয়is
তাধগ ম্যাকডোনাল্ড-জেনসেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.