আরও দক্ষ কী: অভিধান ট্রাইগেটভ্যালু বা কনটেন্সকি + আইটেম?


251

অভিধানে এমএসডিএন এর প্রবেশ থেকে: ট্রাইগেটভ্যালু পদ্ধতি :

এই পদ্ধতিটি কনটেনস্কি পদ্ধতি এবং আইটেম বৈশিষ্ট্যের কার্যকারিতা একত্রিত করে।

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

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

এই পদ্ধতিটি একটি ও (1) ক্রিয়াকলাপের কাছে চলেছে।

বিবরণ থেকে এটি স্পষ্ট নয় যে এটি কনটেনস্কিকে কল করার পরে অনুসন্ধানটি করার চেয়ে আরও দক্ষ বা আরও সুবিধাজনক। TryGetValueকেবলমাত্র কন্টেনস্কিকে কল করুন এবং তারপরে আইটেমটি প্রয়োগ করুন বা একক অনুসন্ধান করে আসলে এর চেয়ে বেশি দক্ষ?

অন্য কথায়, কী বেশি দক্ষ (উদাহরণস্বরূপ কোনটি কম অনুসন্ধান করে):

Dictionary<int,int> dict;
//...//
int ival;
if(dict.ContainsKey(ikey))
{
  ival = dict[ikey];
}
else
{
  ival = default(int);
}

অথবা

Dictionary<int,int> dict;
//...//
int ival;
dict.TryGetValue(ikey, out ival);

দ্রষ্টব্য: আমি কোনও মানদণ্ড খুঁজছি না!

উত্তর:


313

TryGetValue দ্রুত হবে।

ContainsKeyTryGetValueঅভ্যন্তরীণভাবে প্রকৃত প্রবেশের স্থানটিকে বোঝায় এমন একই চেক ব্যবহার করে । দ্যItemসম্পত্তি আসলে প্রায় অভিন্ন কোড কার্যকারিতা থাকে TryGetValueব্যতীত এটি মিথ্যা ফিরে পরিবর্তে একটি ব্যতিক্রম নিক্ষেপ করা হবে।

মূলত ContainsKeyএরপরে ব্যবহার করা Itemঅনুসন্ধানের কার্যকারিতাটিকে নকল করে, যা এই ক্ষেত্রে গণনার বেশিরভাগ অংশ।


2
এই আরও সূক্ষ্ম হল: if(dict.ContainsKey(ikey)) dict[ikey]++; else dict.Add(ikey, 0);। তবে আমি মনে করি যে সূচকের সম্পত্তি অর্জন এবং সেট ব্যবহৃত TryGetValueহওয়ার পরেও এটি আরও কার্যকর ?
টিম শেমলেটার

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

1
@ জনগার্ডনার হ্যাঁ, যা আমি বলেছিলাম - তবে আপনি যদি কনটেনস্কি করেন তবে আইটেমটি পান, আপনি সেই কাজটি 1x এর পরিবর্তে 2x করছেন।
রিড কোপসি

3
আমি সম্পূর্ণরূপে সম্মত আছি :) আমি কেবল ইঙ্গিত করছিলাম যে আসল উত্স এখন পাওয়া যায়। অন্যান্য উত্তর / ইত্যাদির
জন গার্ডনার

1
কিছুটা সামান্য বিষয়, আপনি যদি একটি বহুবিবাহিত পরিবেশে কোনও আইডিকোয়ারির মাধ্যমে অ্যাক্সেস করেন তবে আমি সর্বদা ট্রিগেটভ্যালু ব্যবহার করতাম কারণ আপনি যখন কনটেনস্কিকে কল করবেন তখন থেকে রাষ্ট্রটি পরিবর্তিত হতে পারে (ট্রাইগেটভ্যালু অভ্যন্তরীণভাবে সঠিকভাবে লক করে দেবে এমন কোনও গ্যারান্টি নেই) তবে এটি সম্ভবত নিরাপদ)
ক্রিস বেরি

91

একটি দ্রুত বেঞ্চমার্ক দেখায় যার TryGetValueসামান্য প্রান্ত রয়েছে:

    static void Main() {
        var d = new Dictionary<string, string> {{"a", "b"}};
        var start = DateTime.Now;
        for (int i = 0; i != 10000000; i++) {
            string x;
            if (!d.TryGetValue("a", out x)) throw new ApplicationException("Oops");
            if (d.TryGetValue("b", out x)) throw new ApplicationException("Oops");
        }
        Console.WriteLine(DateTime.Now-start);
        start = DateTime.Now;
        for (int i = 0; i != 10000000; i++) {
            string x;
            if (d.ContainsKey("a")) {
                x = d["a"];
            } else {
                x = default(string);
            }
            if (d.ContainsKey("b")) {
                x = d["b"];
            } else {
                x = default(string);
            }
        }
   }

এটি উত্পাদন করে

00:00:00.7600000
00:00:01.0610000

উপার্জন ContainsKey + Item40% ধীর হিট এবং শটটি এর একটি এমনকি মিশ্রন অভিমানী সম্পর্কে অ্যাক্সেস।

তদুপরি, আমি যখন প্রোগ্রামটি সর্বদা মিস করি (যেমন সর্বদা সন্ধান করি "b") তখন দুটি সংস্করণ সমান দ্রুত হয়ে যায়:

00:00:00.2850000
00:00:00.2720000

আমি যখন এটি "সমস্ত হিট" করি, তবে, TryGetValueঅবশিষ্টাংশগুলি স্পষ্ট বিজয়ী হয়ে থাকে:

00:00:00.4930000
00:00:00.8110000

11
অবশ্যই এটি প্রকৃত ব্যবহারের ধরণের উপর নির্ভর করে। আপনি যদি প্রায়শই একবার অনুসন্ধানে ব্যর্থ হন তবে TryGetValueতার চেয়ে অনেক এগিয়ে থাকা উচিত। এছাড়াও ... একটি নিটপিক ... DateTimeপারফরম্যান্স পরিমাপ ক্যাপচার করার সেরা উপায় নয়।
এড এস

4
@EdS। আপনি ঠিক বলেছেন, TryGetValueআরও এগিয়ে নেতৃত্বে। আমি "সমস্ত হিট" এবং "সমস্ত মিস" পরিস্থিতি অন্তর্ভুক্ত করার জন্য উত্তরটি সম্পাদনা করেছি।
dasblinkenlight

2
@Luciano ব্যাখ্যা করুন যে আপনি ব্যবহার Any- এই ভালো লেগেছে: Any(i=>i.Key==key)। হ্যাঁ, এটি অভিধানের একটি খারাপ রৈখিক অনুসন্ধান।
ওয়েস্টন

13
DateTime.Nowশুধুমাত্র কয়েকটি এমএসে সঠিক হবে। পরিবর্তে Stopwatchক্লাসটি ব্যবহার করুন System.Diagnostics(যা অনেক উচ্চতর নির্ভুলতা প্রদানের জন্য কভারগুলির অধীনে কোয়েরি পারফরম্যান্স কাউন্টার ব্যবহার করে)। এটি ব্যবহার করাও সহজ।
অ্যালাস্টার মাও

5
অ্যালাস্টার এবং এডের মন্তব্য ছাড়াও - ডেটটাইম.এখন আপনি পিছনে যেতে পারেন, যদি আপনি কোনও সময় আপডেট পান, যেমন ব্যবহারকারী যখন তাদের কম্পিউটারের সময় আপডেট করে থাকে তখন একটি সময় অঞ্চল অতিক্রম করা হয় বা সময় অঞ্চল পরিবর্তন হয় (ডিএসটি, দৃষ্টান্ত). এমন কোনও সিস্টেমে কাজ করার চেষ্টা করুন যা কিছু রেডিও পরিষেবা যেমন জিপিএস বা মোবাইল ফোন নেটওয়ার্কের দ্বারা সরবরাহ করা সময়ের সাথে সিস্টেম ঘড়ি সিঙ্ক করে। ডেটটাইম.নাউ পুরো জায়গা জুড়ে যাবে এবং ডেটটাইম.উটকনো কেবল সেই কারণগুলির মধ্যে একটির সমাধান করে। কেবল স্টপওয়াচ ব্যবহার করুন।
এন্টিডহ

51

যেহেতু এখন পর্যন্ত উত্তরগুলির কোনও উত্তরই প্রকৃতপক্ষে প্রশ্নের উত্তর দেয় না, কিছু গবেষণার পরে আমি এখানে একটি গ্রহণযোগ্য উত্তর পেয়েছি:

আপনি যদি ট্রিগেটভ্যালুটি নিষ্পত্তি করেন তবে আপনি দেখতে পাচ্ছেন যে এটি এটি করছে:

public bool TryGetValue(TKey key, out TValue value)
{
  int index = this.FindEntry(key);
  if (index >= 0)
  {
    value = this.entries[index].value;
    return true;
  }
  value = default(TValue);
  return false;
}

কনটেন্সকি পদ্ধতিটি হ'ল:

public bool ContainsKey(TKey key)
{
  return (this.FindEntry(key) >= 0);
}

সুতরাং আইটেমটি উপস্থিত থাকলে ট্রাইগেটভ্যালু হ'ল কেবল কনটেনস্কি প্লাস একটি অ্যারে লুকআপ।

উৎস

এটি প্রদর্শিত হয় যে ট্রাইগেটওয়ালু কনটেনস্কি + আইটেম সংমিশ্রণের চেয়ে প্রায় দ্বিগুণ দ্রুত হবে।


20

কে যত্নশীল :-)

আপনি সম্ভবত জিজ্ঞাসা করছেন কারণ TryGetValueএটি ব্যবহারের জন্য একটি ব্যথা - সুতরাং এটি কোনও এক্সটেনশন পদ্ধতির সাথে এটিকে সজ্জিত করুন।

public static class CollectionUtils
{
    // my original method
    // public static V GetValueOrDefault<K, V>(this Dictionary<K, V> dic, K key)
    // {
    //    V ret;
    //    bool found = dic.TryGetValue(key, out ret);
    //    if (found)
    //    {
    //        return ret;
    //    }
    //    return default(V);
    // }


    // EDIT: one of many possible improved versions
    public static TValue GetValueOrDefault<K, V>(this IDictionary<K, V> dictionary, K key)
    {
        // initialized to default value (such as 0 or null depending upon type of TValue)
        TValue value;  

        // attempt to get the value of the key from the dictionary
        dictionary.TryGetValue(key, out value);
        return value;
    }

তারপরে কেবল কল করুন:

dict.GetValueOrDefault("keyname")

অথবা

(dict.GetValueOrDefault("keyname") ?? fallbackValue) 

1
@ হেসেইন আমি খুব বিভ্রান্ত হয়ে পড়েছিলাম যে এই পোস্টটি ছাড়াই আমি কীভাবে যথেষ্ট বোকা ছিলাম thisতবে এটি প্রমাণিত হয়েছে যে আমার কোড বেসটিতে আমার পদ্ধতিটি দুবার নকল হয়েছে - একবার এবং একটি ছাড়াও thisতাই আমি কখনই এটি ধরিনি! ঠিক করার জন্য ধন্যবাদ!
সাইমন_উইভার

2
TryGetValueকী উপস্থিত না থাকলে আউট ভ্যালু প্যারামিটারে একটি ডিফল্ট মান নির্ধারণ করে, তাই এটি সহজ করা যায়।
রাফেল স্মিট

2
সরলীকৃত সংস্করণ: পাবলিক স্ট্যাটিক টিভিয়ালিউ গেটভ্যালিউআরডিফল্ট <টি কে, টিভিয়াল> (এই অভিধান <টি কে, টিভিয়াল> ডিক্ট, টি কে কী) {টিভিয়াল রিট; ..TryGetValue (কী, আউট রেট); প্রত্যাবর্তন ret; }
জোশুয়া

2
সি # 7 এ এটি সত্যিই মজাদার:if(!dic.TryGetValue(key, out value item)) item = dic[key] = new Item();
শিমি ওয়েটজ্যান্ডলার

1
হাস্যকরভাবে, আসল উত্স কোডটি ইতিমধ্যে একটি getValueOrDefault () রুটিন রয়েছে, তবে এটি লুকানো আছে ... রেফারেন্সসোর্স.মাইক্রোসফটকম
দেবেন টি। করজাইন

10

আপনি এটি পরীক্ষা করেন না কেন?

তবে আমি এটা নিশ্চিত TryGetValue এটি দ্রুত, কারণ এটি কেবল একটি অনুসন্ধান করে lookup অবশ্যই এটি গ্যারান্টিযুক্ত নয়, অর্থাত্ বিভিন্ন বাস্তবায়নে বিভিন্ন কার্য সম্পাদনের বৈশিষ্ট্য থাকতে পারে।

আমি অভিধানটি যেভাবে প্রয়োগ করব তা হ'ল একটি অভ্যন্তরীণ Findফাংশন তৈরি করে যা কোনও আইটেমের স্লট সন্ধান করে এবং তারপরে বাকী অংশটি তৈরি করে।


আমি মনে করি না বাস্তবায়নের বিশদগুলি সম্ভবত গ্যারান্টিটি পরিবর্তন করতে পারে যে এক্স এক্স একবার করা একবার এক্স এক্স করার চেয়ে দু'বার দ্রুত বা সমান। সেরা ক্ষেত্রে তারা অভিন্ন, আরও খারাপ ক্ষেত্রে 2 এক্স সংস্করণ দ্বিগুণ সময় নেয় takes
ড্যান বেচার্ড

9

এখন পর্যন্ত সমস্ত উত্তর ভাল, যদিও, একটি গুরুত্বপূর্ণ পয়েন্ট মিস।

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

যেমন, গতি আনুষ্ঠানিক ইন্টারফেস সংজ্ঞা (যা এটি এই ক্ষেত্রে নয়) এর একটি অংশ না হলে এ জাতীয় পদ্ধতিটি কল করা দ্রুত কিনা তা জিজ্ঞাসা করা সাধারণত ভুল।

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

সুতরাং উত্তরটি (গ্রিজলড পুরাতন হ্যাক থেকে) অবশ্যই 'হ্যাঁ' (ট্রাইগেটভ্যালু একটি অভিধান থেকে একটি মান পুনরুদ্ধার করতে কনটেনস্কি এবং আইটেম [গেট] এর সংমিশ্রণের চেয়ে পছন্দনীয়)।

যদি আপনি এইটিকে বিজোড় বলে মনে করেন, তবে এটির মতো চিন্তা করুন: ট্রাইগেটভ্যালু, কনটেনস্কি এবং আইটেমের [বর্তমান] বাস্তবায়ন যদি কোনও গতির পার্থক্য না পেয়ে থাকে তবে আপনি ধরে নিতে পারেন ভবিষ্যতের বাস্তবায়ন (যেমন। নেট ভি 5) করবে (ট্রাইগেটভ্যালু দ্রুত হবে)। আপনার সফ্টওয়্যারটির জীবনকাল সম্পর্কে চিন্তা করুন।

একদিকে যেমন, এটি লক্ষণীয় আকর্ষণীয় যে সাধারণ আধুনিক ইন্টারফেস সংজ্ঞা প্রযুক্তিগুলি এখনও বিরলভাবে সময়সীমাবদ্ধতাগুলি আনুষ্ঠানিকভাবে সংজ্ঞায়নের কোনও উপায় সরবরাহ করে। হতে পারে। নেট ভি 5?


2
যদিও আমি শব্দার্থবিজ্ঞানের বিষয়ে আপনার যুক্তির সাথে আমি 100% একমত, এটি এখনও পারফরম্যান্স পরীক্ষা করার পক্ষে মূল্যবান। আপনি কখনই বুঝতে পারবেন না যে আপনি যে এপিআই ব্যবহার করছেন এটি কখন সাবমোটিমাল বাস্তবায়ন করে যাতে শব্দার্থগতভাবে সঠিক জিনিসটি ধীর হয়ে যায়, আপনি যদি পরীক্ষা না করেন।
ড্যান বেচার্ড

5

একটি দ্রুত পরীক্ষা প্রোগ্রাম তৈরি করে, অভিধানে ১ মিলিয়ন আইটেম সহ ট্রাইগেটভ্যালু ব্যবহার করে অবশ্যই উন্নতি হয়।

ফলাফল:

1000000 হিট: 45 এমএস এর জন্য কনটেনস্কি + আইটেম

1000000 হিট: 26 মাইলের জন্য ট্রিগেটভ্যালু

পরীক্ষার অ্যাপটি এখানে:

static void Main(string[] args)
{
    const int size = 1000000;

    var dict = new Dictionary<int, string>();

    for (int i = 0; i < size; i++)
    {
        dict.Add(i, i.ToString());
    }

    var sw = new Stopwatch();
    string result;

    sw.Start();

    for (int i = 0; i < size; i++)
    {
        if (dict.ContainsKey(i))
            result = dict[i];
    }

    sw.Stop();
    Console.WriteLine("ContainsKey + Item for {0} hits: {1}ms", size, sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();

    for (int i = 0; i < size; i++)
    {
        dict.TryGetValue(i, out result);
    }

    sw.Stop();
    Console.WriteLine("TryGetValue for {0} hits: {1}ms", size, sw.ElapsedMilliseconds);

}

5

আমার মেশিনে, প্রচুর পরিমাণে র‌্যাম সহ, যখন রিলেস মোডে চালিত হয় (ডিইবিইউজি নয়), এর মধ্যে যদি সমস্ত এন্ট্রি ContainsKeyসমান হয় TryGetValue/try-catchDictionary<> সন্ধান করে।

ContainsKeyকেবলমাত্র কয়েকটি অভিধান এন্ট্রি পাওয়া না গেলে এগুলি সমস্ত MAXVALকিছুকে ছাড়িয়ে যায় (নীচে আমার উদাহরণে ENTRIESকিছু এন্ট্রি মিস না করা থেকে বড় কিছুতে সেট করুন ):

ফলাফল:

Finished evaluation .... Time distribution:
Size: 000010: TryGetValue: 53,24%, ContainsKey: 1,74%, try-catch: 45,01% - Total: 2.006,00
Size: 000020: TryGetValue: 37,66%, ContainsKey: 0,53%, try-catch: 61,81% - Total: 2.443,00
Size: 000040: TryGetValue: 22,02%, ContainsKey: 0,73%, try-catch: 77,25% - Total: 7.147,00
Size: 000080: TryGetValue: 31,46%, ContainsKey: 0,42%, try-catch: 68,12% - Total: 17.793,00
Size: 000160: TryGetValue: 33,66%, ContainsKey: 0,37%, try-catch: 65,97% - Total: 36.840,00
Size: 000320: TryGetValue: 34,53%, ContainsKey: 0,39%, try-catch: 65,09% - Total: 71.059,00
Size: 000640: TryGetValue: 32,91%, ContainsKey: 0,32%, try-catch: 66,77% - Total: 141.789,00
Size: 001280: TryGetValue: 39,02%, ContainsKey: 0,35%, try-catch: 60,64% - Total: 244.657,00
Size: 002560: TryGetValue: 35,48%, ContainsKey: 0,19%, try-catch: 64,33% - Total: 420.121,00
Size: 005120: TryGetValue: 43,41%, ContainsKey: 0,24%, try-catch: 56,34% - Total: 625.969,00
Size: 010240: TryGetValue: 29,64%, ContainsKey: 0,61%, try-catch: 69,75% - Total: 1.197.242,00
Size: 020480: TryGetValue: 35,14%, ContainsKey: 0,53%, try-catch: 64,33% - Total: 2.405.821,00
Size: 040960: TryGetValue: 37,28%, ContainsKey: 0,24%, try-catch: 62,48% - Total: 4.200.839,00
Size: 081920: TryGetValue: 29,68%, ContainsKey: 0,54%, try-catch: 69,77% - Total: 8.980.230,00

আমার কোডটি এখানে:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                const int ENTRIES = 10000, MAXVAL = 15000, TRIALS = 100000, MULTIPLIER = 2;
                Dictionary<int, int> values = new Dictionary<int, int>();
                Random r = new Random();
                int[] lookups = new int[TRIALS];
                int val;
                List<Tuple<long, long, long>> durations = new List<Tuple<long, long, long>>(8);

                for (int i = 0;i < ENTRIES;++i) try
                    {
                        values.Add(r.Next(MAXVAL), r.Next());
                    }
                    catch { --i; }

                for (int i = 0;i < TRIALS;++i) lookups[i] = r.Next(MAXVAL);

                Stopwatch sw = new Stopwatch();
                ConsoleColor bu = Console.ForegroundColor;

                for (int size = 10;size <= TRIALS;size *= MULTIPLIER)
                {
                    long a, b, c;

                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Loop size: {0}", size);
                    Console.ForegroundColor = bu;

                    // ---------------------------------------------------------------------
                    sw.Start();
                    for (int i = 0;i < size;++i) values.TryGetValue(lookups[i], out val);
                    sw.Stop();
                    Console.WriteLine("TryGetValue: {0}", a = sw.ElapsedTicks);

                    // ---------------------------------------------------------------------
                    sw.Restart();
                    for (int i = 0;i < size;++i) val = values.ContainsKey(lookups[i]) ? values[lookups[i]] : default(int);
                    sw.Stop();
                    Console.WriteLine("ContainsKey: {0}", b = sw.ElapsedTicks);

                    // ---------------------------------------------------------------------
                    sw.Restart();
                    for (int i = 0;i < size;++i)
                        try { val = values[lookups[i]]; }
                        catch { }
                    sw.Stop();
                    Console.WriteLine("try-catch: {0}", c = sw.ElapsedTicks);

                    // ---------------------------------------------------------------------
                    Console.WriteLine();

                    durations.Add(new Tuple<long, long, long>(a, b, c));
                }

                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Finished evaluation .... Time distribution:");
                Console.ForegroundColor = bu;

                val = 10;
                foreach (Tuple<long, long, long> d in durations)
                {
                    long sum = d.Item1 + d.Item2 + d.Item3;

                    Console.WriteLine("Size: {0:D6}:", val);
                    Console.WriteLine("TryGetValue: {0:P2}, ContainsKey: {1:P2}, try-catch: {2:P2} - Total: {3:N}", (decimal)d.Item1 / sum, (decimal)d.Item2 / sum, (decimal)d.Item3 / sum, sum);
                    val *= MULTIPLIER;
                }

                Console.WriteLine();
            }
        }
    }

আমার মনে হচ্ছে এখানে কিছু ফিশ করে চলছে। আমি অবাক হয়েছি যে আপনি কখনই পুনরুদ্ধারকৃত মানটি ব্যবহার করেন না এই কারণে অপ্টিমাইজারটি আপনার কনটেনস্কি () চেকগুলি সরিয়ে বা সরলীকরণ করছে।
ড্যান বেচার্ড

এটা ঠিক পারে না। কন্টেনস্কি () একটি সংকলিত ডিএলএল-তে রয়েছে। কন্টেনস্কি () আসলে কী করে সে সম্পর্কে অপ্টিমাইজার কিছুই জানে না। এটি পার্শ্ব প্রতিক্রিয়া সৃষ্টি করতে পারে, সুতরাং এটি কল করতে হবে এবং সংক্ষিপ্ত করা যাবে না।
AxD

এখানে কিছু বোগাস আছে। আসল বিষয়টি হ'ল। নেট কোড পরীক্ষা করে দেখা যায় যে কনটেনস্কি, ট্রাইগেটভ্যালু এবং এই [] সকলেই একই অভ্যন্তরীণ কোডকে কল করে, তাই ট্রাইগেটভ্যালু কনটেনস্কি + এর থেকে দ্রুত [এটি]] উপস্থিতি উপস্থিত থাকলে exists
জিম বাল্টার

3

ব্যবহারিক সেটিংসে সঠিক ফলাফল দেবে এমন একটি মাইক্রোব্যাঙ্কমার্ক ডিজাইন করা ছাড়াও আপনি। নেট ফ্রেমওয়ার্কের রেফারেন্স উত্সটি পরীক্ষা করতে পারেন।

FindEntry(TKey)এঁরা সকলেই সেই পদ্ধতিটিকে কল করে যা বেশিরভাগ কাজ করে এবং এর ফলাফলটি স্মরণ করে না, সুতরাং কল TryGetValueকরা প্রায় ContainsKey+ দ্বিগুণ দ্রুতItem


এর অসুবিধার ইন্টারফেসটি কোনও এক্সটেনশন পদ্ধতি ব্যবহার করে মানিয়ে নেওয়াTryGetValue যেতে পারে :

using System.Collections.Generic;

namespace Project.Common.Extensions
{
    public static class DictionaryExtensions
    {
        public static TValue GetValueOrDefault<TKey, TValue>(
            this IDictionary<TKey, TValue> dictionary,
            TKey key,
            TValue defaultValue = default(TValue))
        {
            if (dictionary.TryGetValue(key, out TValue value))
            {
                return value;
            }
            return defaultValue;
        }
    }
}

যেহেতু সি # 7.1, আপনি default(TValue)প্লেইন দিয়ে প্রতিস্থাপন করতে পারেন defaultপ্রকারটি অনুমান করা হয়।

ব্যবহার:

var dict = new Dictionary<string, string>();
string val = dict.GetValueOrDefault("theKey", "value used if theKey is not found in dict");

এটি এমন nullরেফারেন্স প্রকারের জন্য প্রত্যাবর্তন করে যার চেহারা ব্যর্থ হয়, যতক্ষণ না স্পষ্টভাবে ডিফল্ট মান উল্লেখ করা হয়।

var dictObj = new Dictionary<string, object>();
object valObj = dictObj.GetValueOrDefault("nonexistent");
Debug.Assert(valObj == null);

val dictInt = new Dictionary<string, int>();
int valInt = dictInt.GetValueOrDefault("nonexistent");
Debug.Assert(valInt == 0);

নোট করুন যে এক্সটেনশন পদ্ধতির ব্যবহারকারীরা অস্তিত্বহীন কী এবং বিদ্যমান কীগুলির মধ্যে পার্থক্য বলতে পারবেন না তবে এর মান ডিফল্ট (টি)।
লুকাস

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

2

যদি আপনি অভিধান থেকে মানটি বের করার চেষ্টা করছেন, ট্রাইগেটভ্যালু (কী, আউট মান) সেরা বিকল্প, তবে আপনি যদি পুরানো কীগুলি ওভাররাইট না করে নতুন সন্নিবেশের জন্য কীটির উপস্থিতি যাচাই করছেন, এবং কেবলমাত্র সেই সুযোগের সাথেই, কনটেনস্কি (কী) সেরা বিকল্প, বেঞ্চমার্ক এটি নিশ্চিত করতে পারে:

using System;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections;

namespace benchmark
{
class Program
{
    public static Random m_Rand = new Random();
    public static Dictionary<int, int> testdict = new Dictionary<int, int>();
    public static Hashtable testhash = new Hashtable();

    public static void Main(string[] args)
    {
        Console.WriteLine("Adding elements into hashtable...");
        Stopwatch watch = Stopwatch.StartNew();
        for(int i=0; i<1000000; i++)
            testhash[i]=m_Rand.Next();
        watch.Stop();
        Console.WriteLine("Done in {0:F4} -- pause....", watch.Elapsed.TotalSeconds);
        Thread.Sleep(4000);
        Console.WriteLine("Adding elements into dictionary...");
        watch = Stopwatch.StartNew();
        for(int i=0; i<1000000; i++)
            testdict[i]=m_Rand.Next();
        watch.Stop();
        Console.WriteLine("Done in {0:F4} -- pause....", watch.Elapsed.TotalSeconds);
        Thread.Sleep(4000);

        Console.WriteLine("Finding the first free number for insertion");
        Console.WriteLine("First method: ContainsKey");
        watch = Stopwatch.StartNew();
        int intero=0;
        while (testdict.ContainsKey(intero))
        {
            intero++;
        }
        testdict.Add(intero, m_Rand.Next());
        watch.Stop();
        Console.WriteLine("Done in {0:F4} -- added value {1} in dictionary -- pause....", watch.Elapsed.TotalSeconds, intero);
        Thread.Sleep(4000);
        Console.WriteLine("Second method: TryGetValue");
        watch = Stopwatch.StartNew();
        intero=0;
        int result=0;
        while(testdict.TryGetValue(intero, out result))
        {
            intero++;
        }
        testdict.Add(intero, m_Rand.Next());
        watch.Stop();
        Console.WriteLine("Done in {0:F4} -- added value {1} in dictionary -- pause....", watch.Elapsed.TotalSeconds, intero);
        Thread.Sleep(4000);
        Console.WriteLine("Test hashtable");
        watch = Stopwatch.StartNew();
        intero=0;
        while(testhash.Contains(intero))
        {
            intero++;
        }
        testhash.Add(intero, m_Rand.Next());
        watch.Stop();
        Console.WriteLine("Done in {0:F4} -- added value {1} into hashtable -- pause....", watch.Elapsed.TotalSeconds, intero);
        Console.Write("Press any key to continue . . . ");
        Console.ReadKey(true);
    }
}
}

এটি একটি সত্য উদাহরণ, আমার একটি পরিষেবা রয়েছে যা প্রতিটি "আইটেম" তৈরির জন্য, এটি একটি প্রগতিশীল সংখ্যাকে যুক্ত করে, এই নম্বরটি, আপনি যখনই কোনও নতুন আইটেম তৈরি করেন, অবশ্যই আপনাকে অবশ্যই নিখরচায় খুঁজে পেতে হবে, আপনি যদি কোনও আইটেম মুছলে, বিনামূল্যে নম্বর হয়ে যায় নিখরচায়, অবশ্যই এটি অপ্টিমাইজড নয়, যেহেতু আমার কাছে একটি স্ট্যাটিক ভার রয়েছে যা বর্তমান সংখ্যাটিকে ক্যাশে করে, তবে আপনি যদি সমস্ত সংখ্যা শেষ করেন তবে আপনি 0 থেকে UInt32 এ পুনরায় শুরু করতে পারেন M ম্যাক্সভ্যালু

টেস্ট মৃত্যুদন্ড কার্যকর:
hashtable মধ্যে যোগ করার পদ্ধতি উপাদান ...
মধ্যে 0,5908 সম্পন্ন - বিরতি ....
অভিধানের মধ্যে উপাদানের যোগ করা হচ্ছে ...
মধ্যে 0,2679 সম্পন্ন - বিরতি ....
সন্নিবেশ জন্য প্রথম ফ্রি নম্বর খোঁজা
প্রথম পদ্ধতি :
0,0561-এ কন্টেনস্কি সম্পন্ন - অভিধানে 1000000 যুক্ত মূল্য - বিরতি দিন ....
দ্বিতীয় পদ্ধতি: ট্রাইগেটভ্যালু 0,0643-এ
সম্পন্ন - অভিধানে 1000001 যুক্ত হয়েছে - বিরতি দিন ...
পরীক্ষায় হ্যাশটেবল
সম্পন্ন 0, 3015 - হ্যাশটেবলে 1000000 যুক্ত হওয়া মান - বিরতি দিন ....
চালিয়ে যেতে কোনও কী টিপুন। ।

যদি আপনারা কেউ যদি জিজ্ঞাসা করতে পারেন যে কন্টেনস্কির কোনও সুবিধা থাকতে পারে তবে আমি চেষ্টা করেও কন্টেন্ট কী সহ ট্রাইগেটভ্যালুটি উল্টানোর চেষ্টা করেছি, ফলাফলটি একই।

সুতরাং, আমার জন্য, চূড়ান্ত বিবেচনার সাথে, এটি সমস্ত প্রোগ্রামের আচরণের উপর নির্ভর করে।

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