আমি কখন হ্যাশসেট <টি> টাইপ ব্যবহার করব?


134

আমি অন্বেষণ করছি HashSet<T> প্রকারটি , কিন্তু সংগ্রহের মধ্যে এটি কোথায় দাঁড়িয়েছে তা আমি বুঝতে পারি না।

একটি এটি প্রতিস্থাপন করতে এটি ব্যবহার করতে পারেন List<T>? আমি এটার পারফরম্যান্স HashSet<T>আরও ভাল হবে তা কল্পনা করেছি তবে এর উপাদানগুলিতে স্বতন্ত্র অ্যাক্সেসটি আমি দেখতে পেলাম না।

এটি কি কেবল গণনার জন্য?

উত্তর:


228

নামে গুরুত্বপূর্ণ বিষয়টি HashSet<T>এখানে রয়েছে: এটি একটি সেট । একক সেট দিয়ে কেবলমাত্র আপনি যা করতে পারেন তা হ'ল এর সদস্যরা কী তা প্রতিষ্ঠিত করা এবং কোনও আইটেম সদস্য কিনা তা যাচাই করা।

আপনি যদি একটি একক উপাদান (উদাহরণস্বরূপ set[45]) পুনরুদ্ধার করতে পারেন তা জিজ্ঞাসা করা হচ্ছে সেটটির ধারণাটি ভুল বুঝে। কোনও সেটের 45 তম উপাদান হিসাবে এমন কোনও জিনিস নেই। একটি সেট আইটেম কোন অর্ডার আছে। সেটগুলি {1, 2, 3} এবং, 2, 3, 1 every প্রতিটি ক্ষেত্রে অভিন্ন কারণ তাদের সদস্যপদ একই রকম, এবং সদস্যপদই বিষয়টি গুরুত্বপূর্ণ।

এটিকে পুনরাবৃত্তি করা কিছুটা বিপদজনক HashSet<T> কারণ এটি করা সেটগুলির আইটেমগুলিতে একটি অর্ডার চাপিয়ে দেয়। এই অর্ডারটি আসলে সেটটির সম্পত্তি নয়। আপনার উপর নির্ভর করা উচিত নয়। যদি কোনও সংগ্রহে আইটেমগুলি অর্ডার করা আপনার পক্ষে গুরুত্বপূর্ণ, তবে সংগ্রহটি কোনও সেট নয়।

সেটগুলি সত্যই সীমাবদ্ধ এবং অনন্য সদস্য সহ। অন্যদিকে, তারা সত্যিই দ্রুত।


1
ফ্রেমওয়ার্কটি কোনও SortedSetডেটা স্ট্রাকচার সরবরাহ করে তা হ'ল একটি সংস্থার সম্পত্তি না হওয়ার বিষয়ে আপনি যা বলেছেন তার সাথে বিরোধিতা করে - বা উন্নয়ন দল থেকে কোনও ভুল বোঝাবুঝির নির্দেশ করে।
ভেভারকে

10
আমি মনে করি এটি বলা আরও সঠিক যে আইটেমের ক্রমের HashSetসংজ্ঞা দেওয়া হয়নি, তাই পুনরাবৃত্তির আদেশের উপর নির্ভর করবেন না। আপনি যদি সেটটি পুনরুক্তি করেন কারণ আপনি সেটের আইটেমগুলির বিরুদ্ধে কিছু করছেন, তবে এটি অর্ডার সম্পর্কিত কোনও কিছুর উপর নির্ভর না করা বিপজ্জনক নয় । এ এর প্লাস অর্ডারের সমস্ত বৈশিষ্ট্য রয়েছে তবে তা থেকে প্রাপ্ত হয় না ; পুনঃপ্রকাশিত , একটি সাজানো সেট হ'ল স্বতন্ত্র বস্তুর একটি আদেশযুক্ত সংগ্রহSortedSetHashSet SortedSetHashSet
কিট

110

আমি যেখানে এটি ব্যবহার করি তার আসল উদাহরণ এখানে HashSet<string>:

অবাস্ত্রস্ক্রিপ্ট ফাইলগুলির জন্য আমার সিনট্যাক্স হাইল্ডারের অংশটি একটি নতুন বৈশিষ্ট্য যা ডক্সিজেন-স্টাইলের মন্তব্যগুলিকে হাইলাইট করে । ধূসর (বৈধ) বা লাল (অবৈধ) এ প্রদর্শিত হবে কিনা তা নির্ধারণ করার জন্য আমার @বা \কমান্ডটি বৈধ কিনা তা আমাকে জানাতে সক্ষম হবেন । আমার কাছে HashSet<string>সমস্ত বৈধ কমান্ড রয়েছে, সুতরাং আমি যখনই @xxxলেসারে একটি টোকেন আঘাত করি তখন আমি validCommands.Contains(tokenText)আমার ও (1) বৈধতা পরীক্ষা হিসাবে ব্যবহার করি। বৈধ কমান্ডের সেটে কমান্ডের অস্তিত্ব ব্যতীত আমি সত্যিই কিছুই চিন্তা করি না । যে বিকল্পগুলির মুখোমুখি হয়েছি সেগুলি দেখে আসুন:

  • Dictionary<string, ?>: মানটির জন্য আমি কী ধরণের ব্যবহার করব? মানটি অর্থহীন, যেহেতু আমি কেবল ব্যবহার করতে যাচ্ছি ContainsKey। দ্রষ্টব্য: .NET 3.0 এর আগে এটি ও (1) দেখার জন্য একমাত্র পছন্দ HashSet<T>ছিল - 3.0 এর জন্য যুক্ত করা হয়েছিল এবং ISet<T>4.0 এর জন্য প্রয়োগ করার জন্য এটি বাড়ানো হয়েছিল ।
  • List<string>: আমি যদি তালিকাটি বাছাই করে রাখি তবে আমি ব্যবহার করতে পারি BinarySearch, যা ও (লগ এন) (উপরে বর্ণিত এই সত্যটি দেখেনি)। তবে, যেহেতু আমার বৈধ কমান্ডগুলির তালিকাটি একটি নির্দিষ্ট তালিকা যা কখনই পরিবর্তিত হয় না, এটি কখনও কখনও সহজ ...
  • string[]: আবার, Array.BinarySearchও (লগ এন) সম্পাদন দেয়। যদি তালিকাটি সংক্ষিপ্ত হয় তবে এটি সর্বোত্তম পারফর্মিং বিকল্প হতে পারে। এটা সবসময় কম স্থান ওভারহেড হয়েছে HashSet, Dictionaryঅথবা List। এমনকি BinarySearch, এটি বড় সেটগুলির জন্য দ্রুত নয়, তবে ছোট সেটগুলির জন্য এটি পরীক্ষামূলক worth আমার যদিও বেশ কয়েকশ আইটেম রয়েছে, তাই আমি এটি পেরিয়েছি।

24

একটি ইন্টারফেস HashSet<T>প্রয়োগ করে ICollection<T>:

public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
    // Methods
    void Add(T item);
    void Clear();
    bool Contains(T item);
    void CopyTo(T[] array, int arrayIndex);
    bool Remove(T item);

    // Properties
   int Count { get; }
   bool IsReadOnly { get; }
}

একটি List<T>সরঞ্জাম IList<T>, যা প্রসারিত করেICollection<T>

public interface IList<T> : ICollection<T>
{
    // Methods
    int IndexOf(T item);
    void Insert(int index, T item);
    void RemoveAt(int index);

    // Properties
    T this[int index] { get; set; }
}

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

একটি সেট একটি সংগ্রহ যা কোনও সদৃশ উপাদান নেই এবং যার উপাদানগুলি কোনও নির্দিষ্ট ক্রমে নেই।

হ্যাডসেট কী উপার্জন করতে পারে, যদি এটি সূচক / অবস্থান / তালিকার আচরণ হারায়?

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

একটি হ্যাশসেটের আচরণকে Dictionary<TKey,TValue>কেবলমাত্র কীগুলিকে মান হিসাবে যুক্ত / মুছে ফেলার মাধ্যমে এবং অভিধানের মানগুলিকে উপেক্ষা করে তুলনা করা যেতে পারে । আপনি অভিধানে কীগুলি ডুপ্লিকেট মান না রাখার প্রত্যাশা করবেন এবং এটি "সেট" অংশের মূল বিষয়।


14

পারফরম্যান্স হ্যাশসেটকে ওভার তালিকার চয়ন করার জন্য খারাপ কারণ হবে be পরিবর্তে, আরও ভাল আপনার অভিপ্রায় ক্যাপচার? যদি অর্ডারটি গুরুত্বপূর্ণ হয় তবে সেট (বা হ্যাশসেট) আউট। যদি অনুরূপ অনুমতি দেওয়া হয়, একইভাবে। তবে এমন অনেক পরিস্থিতিতে রয়েছে যখন আমরা অর্ডারটি যত্ন করি না এবং ডুপ্লিকেটগুলিও রাখি না - এবং এটিই যখন আপনি সেট চান।


21
Performance would be a bad reason to choose HashSet over List: আমি শুধু তোমার সাথে একমত হই না। এ জাতীয় কথা বলা যে দুটি তালিকার পরিবর্তে একটি ডিকশন্রে নির্বাচন করা কার্য সম্পাদনে সহায়তা করে না। কটাক্ষপাত নিম্নলিখিত নিবন্ধ
অস্কার Mederos

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

2
তবে এটি সম্পর্কে চিন্তা করুন। যদি আপনি পরীক্ষা করে দেখতে চান যে প্রদত্ত স্ট্রিংগুলি প্রযুক্তিগতভাবে 10,000 স্ট্রিংয়ের কোনও সংগ্রহের সদস্য কিনা string[].Containsএবং HashSet<string>.Containsআপনার উদ্দেশ্যটি সমানভাবে প্রকাশ করুন; হ্যাশসেটটি বাছাই করার কারণ এটি অনেক দ্রুত চলবে।
কেসি

12

হ্যাশসেট হ্যাশিং দ্বারা প্রয়োগ করা একটি সেট । একটি সেট হ'ল মানগুলির সংগ্রহ যা কোনও সদৃশ উপাদান নেই। একটি সেটের মানগুলিও সাধারণত আনর্ডারড থাকে। সুতরাং না, একটি তালিকা কোনও প্রতিস্থাপন করতে ব্যবহার করা যাবে না (যদি না আপনি প্রথমে একটি সেট ব্যবহার না করেন)।

যদি আপনি ভাবছেন যে কোনও সেটটি কী জন্য ভাল হতে পারে: যে কোনও জায়গায় আপনি নকলগুলি থেকে মুক্তি পেতে চান, অবশ্যই ly কিছুটা স্বল্প উদাহরণ হিসাবে বলা যাক, আপনার কাছে একটি সফ্টওয়্যার প্রকল্পের ১০,০০০ সংশোধনীর একটি তালিকা রয়েছে এবং কতজন লোক সেই প্রকল্পে অবদান রেখেছিল তা আপনি জানতে চান। আপনি Set<string>সংশোধনগুলির তালিকার উপরে একটি এবং পুনরাবৃত্তি করতে পারেন এবং প্রতিটি সংশোধনের লেখককে সেটে যুক্ত করতে পারেন। একবার আপনি পুনরাবৃত্তি সম্পন্ন করার পরে, সেটটির আকার আপনি যে উত্তরটি খুঁজছিলেন তা হ'ল।


কিন্তু সেট একক উপাদান পুনরুদ্ধারের অনুমতি দেয় না? সেট পছন্দ [45]?
জোয়ান ওয়েঙ্গে

2
তার জন্য, আপনি সদস্যদের সেটটি পুনরাবৃত্তি করতে চাই। অন্যান্য সাধারণ ক্রিয়াকলাপগুলি সেটে কোনও উপাদান রয়েছে বা সেটের আকার পাচ্ছে কিনা তা পরীক্ষা করে দেখছে।
আর্ল করুন

11

হ্যাশসেটটি একটি মূল সংকলনে সদৃশ উপাদানগুলি অপসারণ করতে ব্যবহৃত হবে। উদাহরণ স্বরূপ,

List<string> duplicatedEnumrableStrings = new List<string> {"abc", "ghjr", "abc", "abc", "yre", "obm", "ghir", "qwrt", "abc", "vyeu"};
HashSet<string> uniqueStrings = new HashSet(duplicatedEnumrableStrings);

এই কোডগুলি চালনার পরে, ইউনিক্স স্ট্রিংসগুলিতে {"এবিসি", "গজর", "ইয়ার", "ওবএম", "কিউআরটি", "ভাইয়ু" holds;


6

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

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


যদি আপনি কেবল সেগুলি দিয়ে পুনরাবৃত্তি করেন তবে হ্যাশসেট পদ্ধতি তালিকার তুলনায় বেশ কিছুটা মেমরি ব্যবহার যুক্ত করে।
স্যামুয়েলওয়ারেন

5

HashSet<T>.NET ফ্রেমওয়ার্কের একটি ডেটা স্ট্রুকুট যা একটি বস্তু হিসাবে গাণিতিক সেট উপস্থাপন করতে সক্ষম । এই ক্ষেত্রে, GetHashCodeসেট উপাদানগুলির সাম্যের তুলনা করতে এটি হ্যাশ কোডগুলি ( প্রতিটি আইটেমের ফলাফল) ব্যবহার করে।

একটি তালিকা একটি তালিকা থেকে পৃথক হয় যা এটি কেবলমাত্র এর মধ্যে থাকা একই উপাদানগুলির একটি ঘটনাকে মঞ্জুরি দেয়। আপনি যদি দ্বিতীয় অভিন্ন উপাদান যুক্ত করার চেষ্টা করেন তবে তা HashSet<T>ফিরে আসবে false। প্রকৃতপক্ষে, উপাদানগুলির সন্ধান খুব দ্রুত (O(1) সময়), যেহেতু অভ্যন্তরীণ ডেটা কাঠামো কেবল একটি হ্যাশটেবল।

আপনি কোন ব্যবহার করতে হতাশ থাকেন, তবে মনে রাখবেন, যে ব্যবহার List<T>যেখানে HashSet<T>appropiate নয় সবচেয়ে বড় ভুল হয়েছে, অথচ তা সম্ভাব্য যেখানে আপনি আপনার সংগ্রহে অবাঞ্ছিত ডুপ্লিকেট আইটেম আছে সমস্যার অনুমতি দিতে পারে হয়। আরও কী, O(1)লুক (আইটেম পুনরুদ্ধার) সময়ের চেয়ে আরও বেশি কার্যকর - আদর্শভাবে (নিখুঁত বকেটিংয়ের জন্য) O(n)সময়ের পরিবর্তে - যা অনেক পরিস্থিতিতে বেশ গুরুত্বপূর্ণ।


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

1
@ sepp2k: হ্যাঁ, তাই এটি একটি বুলিয়ান ফেরত দেয় ... মূল কথাটি, এটি আপনাকে অবহিত করে। এবং হ্যাশ চেহারাটি সবচেয়ে খারাপ ক্ষেত্রে ও (এন) হয় যদি আপনি বকেটিং বিপজ্জনক হন - এটি সাধারণভাবে ও (1) এর অনেক কাছাকাছি।
নলডোরিন

4

List<T>অর্ডার করা তথ্যের সেটগুলি সঞ্চয় করতে ব্যবহৃত হয়। আপনি যদি তালিকার উপাদানগুলির আপেক্ষিক ক্রমটি জানেন তবে আপনি অবিচ্ছিন্ন সময়ে এগুলি অ্যাক্সেস করতে পারেন। তবে তালিকায় কোন উপাদান রয়েছে তা নির্ধারণ করতে বা তালিকায় এটি উপস্থিত রয়েছে কিনা তা পরীক্ষা করতে, দেখার সময়টি লিনিয়ার is অন্য দিকে,HashedSet<T> সঞ্চিত ডেটার ক্রমের কোনও গ্যারান্টি দেয় না এবং ফলস্বরূপ এর উপাদানগুলির জন্য অবিচ্ছিন্ন অ্যাক্সেসের সময় সরবরাহ করে।

নামটি থেকে বোঝা যায়, HashedSet<T>একটি ডেটা স্ট্রাকচার যা সেট শব্দার্থিক প্রয়োগ করে । ডেটা স্ট্রাকচার সেট অপারেশনগুলি (যেমন ইউনিয়ন, ডিফারেন্স, ইন্টারসেক্ট) বাস্তবায়নের জন্য অনুকূলিত হয়েছে, যা traditionalতিহ্যবাহী তালিকা বাস্তবায়নের সাথে দক্ষতার সাথে করা যায় না।

সুতরাং, কোন ডেটা টাইপ ব্যবহার করবেন তা চয়ন করা আপনার অ্যাপ্লিকেশনটির সাথে কী করার চেষ্টা করছেন তার উপর নির্ভর করে। আপনি যদি সংগ্রহগুলিতে আপনার উপাদানগুলি কীভাবে অর্ডার করা হয় সে সম্পর্কে যত্নশীল না হন এবং কেবলমাত্র প্রশংসনীয় বা অস্তিত্বের জন্য যাচাই করতে চান, ব্যবহার করুন HashSet<T>। অন্যথায়, List<T>বা অন্য কোনও উপযুক্ত ডেটা কাঠামো ব্যবহার করে বিবেচনা করুন ।


2
অন্য একটি সতর্কতা: সেটগুলি সাধারণত কোনও উপাদানের কেবলমাত্র একটি ঘটনার অনুমতি দেয়।
স্টিভ গুইদি

1

সংক্ষেপে - যে কোনও সময় আপনি অভিধান (বা অভিধান যেখানে এস টি এর সম্পত্তি হিসাবে) ব্যবহার করতে প্ররোচিত হন তবে আপনার একটি হ্যাশসেট বিবেচনা করা উচিত (বা হ্যাশসেট + টি তে আইকুয়েটেবল কার্যকর করা হবে যা এস এর সমান হবে)


5
আপনি যদি কীটির বিষয়ে চিন্তা না করেন তবে আপনার অভিধানটি ব্যবহার করা উচিত।
হার্ডওয়্যারগুই

1

আপনি HashSet<T>যখন লিনকুই সরবরাহের চেয়ে দুটি সংকলনে আরও সুনির্দিষ্ট সেট ক্রিয়াকলাপ চান তখন মৌলিক উদ্দেশ্যে পরিস্থিতিটি ব্যবহার করা উচিত। LINQ পদ্ধতি পছন্দ Distinct, Union, Intersectএবং Exceptসবচেয়ে পরিস্থিতিতে যথেষ্ট, কিন্তু কখনও কখনও আপনি আরো নিখুঁতভাবে অপারেশন প্রয়োজন হতে পারে, এবং HashSet<T>প্রদান করে:

  • UnionWith
  • IntersectWith
  • ExceptWith
  • SymmetricExceptWith
  • Overlaps
  • IsSubsetOf
  • IsProperSubsetOf
  • IsSupersetOf
  • IsProperSubsetOf
  • SetEquals

লিনকিউ এবং HashSet<T>"ওভারল্যাপিং" পদ্ধতির মধ্যে আরেকটি পার্থক্য হ'ল লিনিকুই সর্বদা একটি নতুন ফিরিয়ে দেয় IEnumerable<T>এবং HashSet<T>পদ্ধতিগুলি উত্স সংগ্রহটি পরিবর্তন করে।

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