অভিধানে কী আছে কিনা তা পরীক্ষা করা তত দ্রুত কেন ব্যতিক্রম ব্যতীত ধরা পড়ার চেয়ে?


234

কোডটি কল্পনা করুন:

public class obj
{
    // elided
}

public static Dictionary<string, obj> dict = new Dictionary<string, obj>();

পদ্ধতি 1

public static obj FromDict1(string name)
{
    if (dict.ContainsKey(name))
    {
        return dict[name];
    }
    return null;
}

পদ্ধতি 2

public static obj FromDict2(string name)
{
    try
    {
        return dict[name];
    }
    catch (KeyNotFoundException)
    {
        return null;
    }
}

এই 2 টি কার্য সম্পাদনের ক্ষেত্রে পার্থক্য থাকলে আমি কৌতূহলী ছিলাম, কারণ প্রথমটির দ্বিতীয়টির চেয়ে কম হওয়া উচিত - অভিধানের কোনও মান রয়েছে কিনা তা দ্বিগুণ পরীক্ষা করা দরকার, দ্বিতীয় ফাংশনটিতে কেবল অভিধান অ্যাক্সেস করতে হবে একবার কিন্তু ওয়াও, এটি আসলে বিপরীত:

1 000 000 মানগুলির জন্য লুপ (100,000 বিদ্যমান এবং 900,000 বিদ্যমান নেই):

প্রথম ফাংশন: 306 মিলিসেকেন্ড

দ্বিতীয় ফাংশন: 20483 মিলিসেকেন্ড

তা কেন?

সম্পাদনা: আপনি এই প্রশ্নের নীচে মন্তব্যগুলিতে লক্ষ্য করতে পারেন, দ্বিতীয় অস্তিত্বের কার্যকারিতা 0 টি বিদ্যমান কী নেই এমন ক্ষেত্রে প্রথমটির তুলনায় কিছুটা ভাল। তবে একবার কমপক্ষে 1 বা ততোধিক অ-বিদ্যমান কী থাকলে, দ্বিতীয়টির পারফরম্যান্স দ্রুত হ্রাস পায়।


39
প্রথমটি কেন ধীর হওয়া উচিত ? আসলে, প্রথম নজরে, আমি বলব এটি দ্রুত হওয়া উচিত, ContainsKeyপ্রত্যাশিত O(1)...
প্যাট্রিক ieউইক


8
@ পেটার ব্যতিক্রম ছোঁড়ার চেয়ে আরও অনেক বেশি নির্দেশাবলী জড়িত রয়েছে O(1) অনুসন্ধানের ... বিশেষত যেহেতু দুটি O(1)অপারেশন করা এখনও অনিচ্ছাকৃতভাবে O(1)
প্যাট্রিক ieউইক

9
নীচের ভাল উত্তরে যেমন উল্লেখ করা হয়েছে, ব্যতিক্রম ছোঁড়া ব্যয়বহুল। তাদের নাম এটির পরামর্শ দেয়: এগুলি ব্যতিক্রমী- পরিস্থিতিতে জন্য সংরক্ষিত বোঝানো হয় । আপনি যদি এমন কোনও লুপ চালাচ্ছেন যেখানে আপনি কোনও অভিধানের কোয়ালিটি মিলের জন্য মিলিয়ন বার জিজ্ঞাসা করছেন যা অস্তিত্বহীন, তবে এটি সাজানোর ক্ষেত্রে ব্যতিক্রমী পরিস্থিতি হয়ে যায়। আপনি যদি কীগুলির জন্য অভিধান জিজ্ঞাসা করছেন, এবং এটি তুলনামূলকভাবে সাধারণ ক্ষেত্রে যে কীগুলি উপস্থিত থাকবে না, তবে প্রথমে এটি পরীক্ষা করা বুদ্ধিমান।
জেসন আর 14

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

উত্তর:


404

একদিকে, ব্যাতিক্রম ছুঁড়ে ফেলা সহজাতভাবে ব্যয়বহুল , কারণ স্ট্যাকটি অযৌক্তিক হতে হবে
the অন্যদিকে, কোনও অভিধানে এর কী দ্বারা কোনও মান অ্যাক্সেস করা সস্তা, কারণ এটি একটি দ্রুত, ও (1) ক্রিয়াকলাপ।

বিটিডাব্লু: এটি করার সঠিক উপায়টি হ'ল ব্যবহার করা TryGetValue

obj item;
if(!dict.TryGetValue(name, out item))
    return null;
return item;

এটি অভিধানটি একবারে একবারের পরিবর্তে একবার অ্যাক্সেস করে।
আপনি যদি সত্যই nullকীটি উপস্থিত না থাকলে কেবল ফিরে আসতে চান , উপরের কোডটি আরও সহজ করা যেতে পারে:

obj item;
dict.TryGetValue(name, out item);
return item;

এটি কাজ করে, কারণ কোনও কী উপস্থিত থাকলে তা TryGetValueসেট itemকরে ।nullname


4
আমি উত্তর অনুযায়ী আমার পরীক্ষা আপডেট করেছি, এবং কোনও কারণে, প্রস্তাবিত ফাংশনটি দ্রুততর হওয়া সত্ত্বেও, এটি আসলে খুব তাত্পর্যপূর্ণ নয়: 264 এমএস মূল, 258 মিমি একটি প্রস্তাব করেছে
পেট্র

52
@ পেটার: হ্যাঁ, এটি তাত্পর্যপূর্ণ নয়, কারণ অভিধানটি অ্যাক্সেস করা খুব দ্রুত, আপনি যদি একবার বা দু'বার করে থাকেন তবে তা সত্যিই কিছু যায় আসে না। সম্ভবত এই 250 টি এমএসের বেশিরভাগই পরীক্ষার লুপে ব্যয় হয়।
ড্যানিয়েল হিলগার্থ

4
এটি জেনে রাখা ভাল, কারণ কখনও কখনও এই ধারণাটি পাওয়া যায় যে ব্যতিক্রমী ফাইল বা নাল পয়েন্টারের মতো পরিস্থিতি পরিচালনা করার জন্য ব্যতিক্রম-ছোঁড়া একটি ভাল বা ক্লিনার উপায় those পরিস্থিতিগুলি সাধারণ কিনা এবং পারফরম্যান্স ব্যয়ের বিষয়টি বিবেচনা না করেই।
LarsH

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

8
@ লার্শ এটিও মনে রাখবেন যে কোনও ফাইল (বা অন্য কোনও বাহ্যিক সংস্থান) অ্যাক্সেস করার চেষ্টা করার সময়, এটি চেক এবং প্রকৃত অ্যাক্সেসের চেষ্টার মধ্যে রাষ্ট্র পরিবর্তন করতে পারে। এই ক্ষেত্রে, ব্যতিক্রমগুলি ব্যবহার করা সঠিক উপায়। অতিরিক্ত অন্তর্দৃষ্টি জন্য এই প্রশ্নের স্টিফেন সি এর উত্তর দেখুন ।
yoniLavi

6

ডিকোচারগুলি বিশেষত সুপার ফাস্ট কী লুকআপ করার জন্য ডিজাইন করা হয়েছে। এগুলি হ্যাশ টেবিল হিসাবে প্রয়োগ করা হয় এবং অন্যান্য পদ্ধতির তুলনায় তত বেশি এন্ট্রি তত দ্রুত হয়। ব্যতিক্রম ইঞ্জিনটি ব্যবহার করা কেবল তখনই করা উচিত যখন আপনার পদ্ধতিটি আপনি যা ডিজাইন করেছেন তা করতে ব্যর্থ হয়েছে কারণ এটি একটি বৃহত অবজেক্ট যা আপনাকে ত্রুটিগুলি পরিচালনা করার জন্য অনেক কার্যকারিতা দেয়। একবার চেষ্টা ক্যা ব্লক দিয়ে ঘিরে থাকা সমস্ত কিছু দিয়ে আমি একবারে একটি পুরো লাইব্রেরি ক্লাস তৈরি করেছি এবং over০০ এরও বেশি ব্যতিক্রমের প্রত্যেকটির জন্য আলাদা আলাদা লাইন থাকা ডিবাগ আউটপুটটি দেখে হতবাক হয়েছি!


1
ভাষা প্রয়োগকারীরা যখন সিদ্ধান্ত নিচ্ছেন যে কোথায় অপ্টিমাইজেশনে প্রচেষ্টা ব্যয় করবেন, হ্যাশ টেবিলগুলি অগ্রাধিকার পাবে কারণ তারা প্রায়শই অভ্যন্তরীণ লুপগুলিতে বাধা হয়ে থাকতে পারে used ব্যতিক্রমগুলি কেবলমাত্র খুব কম ঘন ঘন ব্যবহার করা হবে বলে আশা করা হয়, অস্বাভাবিক ("ব্যতিক্রমী", তাই কথা বলার জন্য) ক্ষেত্রে, সুতরাং এগুলি সাধারণত সম্পাদনের জন্য গুরুত্বপূর্ণ হিসাবে বিবেচিত হয় না।
বর্মার

"এগুলি হ্যাশ টেবিল হিসাবে প্রয়োগ করা হয় এবং অন্যান্য পদ্ধতির তুলনায় তত বেশি এন্ট্রিগুলি তত দ্রুত হয়" " যদি বালতিগুলি পূরণ হয় তবে তা সত্য নয়!?!?!
অ্যান্টনি ল্যামবার্ট

1
@ অ্যান্থনি ল্যামবার্ট তিনি যা বলতে চাইছেন তা হ্যাশ টেবিল অনুসন্ধানে ও (1) সময় জটিলতা রয়েছে, এবং বাইনারি অনুসন্ধানের ট্রি অনুসন্ধানে ও (লগ (এন)) থাকবে; গাছ হতাশায় ধীরে ধীরে উপাদানগুলির সংখ্যা বৃদ্ধি করে, হ্যাশটেবলটি না করে। অতএব, হ্যাশটেবলের গতির সুবিধা উপাদানগুলির সংখ্যা সহ বৃদ্ধি পায়, যদিও এটি ধীরে ধীরে করে does
ডোভাল

@ অ্যান্থনি ল্যামবার্ট সাধারণ ব্যবহারের অধীনে অভিধানের হ্যাশটেবলে খুব কম সংঘর্ষ রয়েছে। যদি আপনি কোনও হ্যাশটেবল ব্যবহার করেন এবং আপনার বালতিগুলি পূরণ হয়, তবে আপনার অনেক এন্ট্রি (বা খুব কম বালতি) রয়েছে a সেক্ষেত্রে একটি কাস্টম হ্যাশ টেবিল ব্যবহার করার সময় এসেছে।
অ্যান্ড্রুস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.