কী। নেট সংগ্রহ দ্রুততম অনুসন্ধান সরবরাহ করে


143

আমার কাছে 60k আইটেম রয়েছে যা 20 কে দেখার তালিকার বিরুদ্ধে পরীক্ষা করা দরকার। একটি সংগ্রহ বস্তু (যেমন List, HashTable) একটি ব্যতিক্রমী দ্রুত Contains()পদ্ধতি সরবরাহ করে? নাকি আমার নিজের লিখতে হবে? অন্য শব্দে, ডিফল্ট Contains()পদ্ধতিটি কেবল প্রতিটি আইটেমটি স্ক্যান করে বা এটি আরও ভাল অনুসন্ধান অ্যালগরিদম ব্যবহার করে।

foreach (Record item in LargeCollection)
{
    if (LookupCollection.Contains(item.Key))
    {
       // Do something
    }
}

নোট । চেহারা তালিকা ইতিমধ্যে বাছাই করা হয়েছে।


তালিকার জন্য থাকা বস্তুর তালিকার জন্য কাজ করে না কারণ এটি রেফারেন্সগুলির সাথে তুলনা করে।
ফিউর

2
সাজানো ডেটা? বাইনারি অনুসন্ধান - @ মার্কের উত্তর দেখুন।
হামিশ স্মিথ

হ্যাশ টেবিল আমার অভিজ্ঞতায় 2 মি আইটেম পর্যন্ত কিছু হারাতে পারে
ক্রিস এস

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

2
আপনি যদি এই জিনিসটি সহজ করতে চান তবে একটি হ্যাশसेट এড়ানোর জন্য সিস্টেম.কলেশনস.জেনারিক.সোর্টড লিস্ট (টি কে, টিভিয়াল) সম্পর্কে ভুলে যাবেন না।
ব্রায়ান

উত্তর:


141

সবচেয়ে সাধারণ ক্ষেত্রে, বিবেচনা System.Collections.Generic.HashSetহিসাবে আপনার ডিফল্ট "রয়েছে" workhorse ডাটা স্ট্রাকচার, কারণ এটি নির্ণয় করা ধ্রুবক সময় লাগে Contains

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


36
দ্রষ্টব্য: হ্যাশকোড ফাংশনটিকে ওভাররাইড করতে ভুলবেন না। যোগ করা পারফরম্যান্সের জন্য, আপনার কনস্ট্রাক্টরে আপনার হ্যাশকোড তৈরি করুন।
ব্রায়ান

1
@ ব্রায়ান: ভালো কথা। আমি ধরে নিচ্ছিলাম (ভিত্তিহীনভাবে) রেকর্ড। কে হ'ল এক ধরণের বিল্টিন টাইপ type
জিমি

3
@ ব্রায়ান: প্রিজারেটের পরিবর্তে আমি প্রথমবার উত্পন্ন উত্সটিকে সংরক্ষণ করতে পছন্দ করি, কেন আপনি এমন কিছু দিয়ে নির্মাণকারীর গতি কম করবেন যা আপনি জানেন না যে এটি ব্যবহার করা হবে কিনা?
jmservra

8
এফওয়াইআই: পারফরম্যান্স পরীক্ষা - আমি স্ট্রিংগুলির জন্য তালিকা <টি> এবং হ্যাশসেট <টি> এর মধ্যে একটি তুলনা তৈরি করেছি। আমি দেখেছি যে হ্যাশসেটটি তালিকার চেয়ে প্রায় 1000 গুণ বেশি দ্রুত।
কোয়াঙ্গো

10
@ কোয়াঙ্গো: 3 বছর পরে, তবে সত্যই যদি আপনি আপনার ডেটার আকারের সেটটি নির্দিষ্ট না করেন তবে এই পারফরম্যান্স তুলনাটির অর্থ কিছুই নেই: হ্যাশেটসগুলিতে ও (1) অনুসন্ধান রয়েছে, তালিকাগুলিতে ও (এন) অনুসন্ধান রয়েছে, সুতরাং পারফরম্যান্স অনুপাতটি আনুপাতিক এন।
ক্লাইমেন্ট

73

যদি আপনার অর্ডার দেওয়ার প্রয়োজন না হয়, চেষ্টা করুন HashSet<Record>(নেট থেকে 3.5। নতুন)

আপনি যদি করেন, একটি List<Record>এবং কল ব্যবহার করুন BinarySearch



2
অথবা আরও ভাল, ImmutableSortedSetসিস্টেম থেকে.আমি পরিবর্তনযোগ্য সংগ্রহগুলি
আলেক্সি এস

24

আপনি বিবেচনা করেছেন List.BinarySearch(item)?

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


1
আপনি ঠিক বলেছেন, পরিবর্তনযোগ্য বস্তুগুলিকে কী হিসাবে ব্যবহার করার সময় একটি হ্যাশ কিছু অযাচিত সমস্যা আনতে পারে।
jmservra

10

আপনার এই ব্লগটি পড়া উচিত যা একক এবং বহু-থ্রেডযুক্ত উভয় কৌশলই ব্যবহার করে প্রত্যেকের জন্য বিভিন্ন ধরণের সংগ্রহ এবং পদ্ধতিগুলির গতি পরীক্ষা করেছিল।

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

"কী" এর জন্য মঞ্জুরি দেয় এমন কোনও সংগ্রহ ব্যবহার করার সময় অভিধান, সাম্প্রতিক অভিধান, হ্যাশসেট এবং হ্যাশ টেবিলগুলি সামগ্রিকভাবে সেরা সম্পাদন করে।


4

উভয় তালিকাগুলি x এবং y অনুসারে বাছাই করুন।

যদি x = y হয় তবে আপনার ক্রিয়াটি করুন, যদি x <y, অগ্রিম x, যদি y <x হয় তবে উভয় তালিকা খালি না হওয়া পর্যন্ত অগ্রণী y করুন।

এই ছেদটি চালানোর সময়টি ন্যূনতম (আকার (x), আকার (y)) এর সমানুপাতিক

একটি .Contains () লুপ চালাবেন না , এটি x * y এর সাথে সমানুপাতিক যা এটি আরও খারাপ।


আরও দক্ষ অ্যালগরিদমের জন্য +1। এমনকি তালিকাগুলি বর্তমানে অরসোর্টড থাকলেও প্রথমে সেগুলি বাছাই করা এবং তারপরে এই অ্যালগরিদমটি চালানো আরও দক্ষ।
ম্যাট বোহেম

যদিও রানটাইমটি সবচেয়ে খারাপ অবস্থায় সর্বাধিক (আকার (x), আকার (y)) এর সমানুপাতিক হবে না? উদাহরণ: int [] x = {99,100}; int [] y = {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
ম্যাট বোহেম

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

3

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

যাইহোক, যদি উভয় তালিকে বাছাইযোগ্য হয় তবে অনুসন্ধান তালিকার ক্রম অনুসারে চলার বিষয়টি কেবল।

Walk lookup list
   While items in check list <= lookup list item
     if check list item = lookup list item do something
   Move to next lookup list item

হ্যাঁ, তাই সত্য। আপনার যদি দু'টি সাজানো তালিকাগুলি থাকে তবে কেবলমাত্র একবারে আপনাকে ট্র্যাভার করতে হবে।
ড্যানভার

3

আপনি। নেট 3.5 ব্যবহার করছেন, আপনি ক্লিনার কোড ব্যবহার করে করতে পারেন:

foreach (Record item in LookupCollection.Intersect(LargeCollection))
{
  //dostuff
}

আমার কাছে নেই। নেট এখানে 3.5 এবং তাই এটি অনির্ধারিত। এটি একটি এক্সটেনশন পদ্ধতির উপর নির্ভর করে। এমন নয় যে LookupCollection.Intersect(LargeCollection)সম্ভবত হিসাবে একই নয় LargeCollection.Intersect(LookupCollection)পরেরটির সম্ভবত গতি অনেক শ্লথ ...।

এটি ধরে নেয় লুকআপ সংগ্রহটি একটি HashSet


2

আপনি যদি প্রতি একক শেষ কার্য সম্পাদন সম্পর্কে উদ্বিগ্ন না হন তবে হ্যাশসেট বা বাইনারি অনুসন্ধান ব্যবহার করার পরামর্শটি শক্ত। আপনার ডেটাসেটগুলি এতটা বড় নয় যে এটি 99% সময়ের সমস্যা হতে চলেছে।

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

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