সমন্বিত কী অভিধান


90

তালিকায় আমার কিছু অবজেক্ট রয়েছে, আসুন List<MyClass>এবং মাইক্লাসের কয়েকটি বৈশিষ্ট্য রয়েছে। আমি মাই ক্লাসের 3 টি বৈশিষ্ট্যের ভিত্তিতে তালিকার একটি সূচক তৈরি করতে চাই। এক্ষেত্রে 2 টি সম্পত্তি ইন্টের এবং একটি সম্পত্তি তারিখের সময়।

মূলত আমি এমন কিছু করতে সক্ষম হতে চাই:

Dictionary< CompositeKey , MyClass > MyClassListIndex = Dictionary< CompositeKey , MyClass >();
//Populate dictionary with items from the List<MyClass> MyClassList
MyClass aMyClass = Dicitonary[(keyTripletHere)];

আমি মাঝে মাঝে ক্লাসের বিভিন্ন বিভাগের বৈশিষ্ট্যগুলির তালিকাতে একাধিক অভিধান তৈরি করি। সম্মিলিত কীগুলি হ্যান্ডেল করার বিষয়ে আমি নিশ্চিত নই। আমি তিনটি মানের একটি চেকসাম করা বিবেচনা করেছি কিন্তু এটি সংঘর্ষের ঝুঁকি চালায়।


4
আপনি টিপলস ব্যবহার করবেন না কেন? তারা আপনার জন্য সমস্ত রচনা তৈরি করে।
এল্ড্রিচ কনড্রাম

21
আমি জানি না যে কীভাবে প্রতিক্রিয়া জানাতে হয়। আপনি এই প্রশ্নটি এমনভাবে জিজ্ঞাসা করলেন যেন আপনি ধরে নিয়েছেন আমি ইচ্ছাকৃতভাবে টিপলগুলি এড়ানো হচ্ছে।
অ্যারোনএলএস

6
দুঃখিত, আমি আরও বিস্তারিত উত্তর হিসাবে এটি আবার লিখেছি।
এল্ড্রিচ কনড্রুম

4
- (যেমন ভয়ানক প্রহেলিকা দ্বারা প্রস্তাবিত) Tuple সম্পর্কে পড়তে একটি কাস্টম বর্গ বাস্তবায়ন করার আগে msdn.microsoft.com/en-us/library/system.tuple.aspx । এগুলি পরিবর্তন করা সহজ এবং আপনার পছন্দসই ক্লাসগুলির তৈরি রক্ষা করবে।
ওএসএইচ

উত্তর:


105

আপনি tuples ব্যবহার করা উচিত। এগুলি একটি কম্পোজিটকি শ্রেণীর সমতুল্য, তবে ইক্যুয়াল () এবং গেটহ্যাশকোড () ইতিমধ্যে আপনার জন্য প্রয়োগ করা হয়েছে।

var myClassIndex = new Dictionary<Tuple<int, bool, string>, MyClass>();
//Populate dictionary with items from the List<MyClass> MyClassList
foreach (var myObj in myClassList)
    myClassIndex.Add(Tuple.Create(myObj.MyInt, myObj.MyBool, myObj.MyString), myObj);
MyClass myObj = myClassIndex[Tuple.Create(4, true, "t")];

অথবা System.Linq ব্যবহার করে

var myClassIndex = myClassList.ToDictionary(myObj => Tuple.Create(myObj.MyInt, myObj.MyBool, myObj.MyString));
MyClass myObj = myClassIndex[Tuple.Create(4, true, "t")];

আপনার হ্যাশের গণনা কাস্টমাইজ করার প্রয়োজন না হলে, টিপলগুলি ব্যবহার করা সহজ।

আপনি যদি সংযুক্ত কীতে প্রচুর সংখ্যক বৈশিষ্ট্য অন্তর্ভুক্ত করতে চান তবে টিপল টাইপের নামটি বেশ দীর্ঘ হতে পারে তবে আপনি টুপলে <...> থেকে নিজের শ্রেণি তৈরি করে নামটি আরও ছোট করতে পারেন।


** 2017 সালে সম্পাদিত **

সি # 7 দিয়ে শুরু করে একটি নতুন বিকল্প রয়েছে: মান টিপলস । ধারণাটি একই, তবে বাক্য গঠনটি ভিন্ন, হালকা:

প্রকারটি Tuple<int, bool, string>হয়ে যায় (int, bool, string), এবং মান Tuple.Create(4, true, "t")হয়ে যায় (4, true, "t")

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


4
টিপল কোনও কীটির পক্ষে ভাল প্রার্থী নয় কারণ এটি উচ্চ সংখ্যক হ্যাশের সংঘর্ষ তৈরি করে। stackoverflow.com/questions/12657348/…
পাপারাজ্জো

4
@ ব্লেম KeyValuePair<K,V>এবং অন্যান্য স্ট্রাক্টের একটি ডিফল্ট হ্যাশ ফাংশন রয়েছে যা খারাপ হিসাবে পরিচিত ( আরও তথ্যের জন্য stackoverflow.com/questions/3841602/… দেখুন)। Tuple<>তবে এটি একটি মান টাইপ নয় এবং এর ডিফল্ট হ্যাশ ফাংশন অন্তত সমস্ত ক্ষেত্র ব্যবহার করবে। বলা হচ্ছে, যদি আপনার কোডের মূল সমস্যাটি সংঘর্ষ হয়, তবে GetHashCode()আপনার ডেটা অনুসারে এমন একটি অনুকূলিত প্রয়োগ করুন।
এল্ড্রিচ কনড্রাম

4
যদিও টিপল আমার পরীক্ষা থেকে কোনও মূল্যবান টাইপ নয় এটি এএএএএএ এর প্রচুর সংঘর্ষে ভুগছে
পাপারাজ্জো

4
আমি মনে করি এই উত্তরটি এখন পুরানো হয়েছে যে আমাদের কাছে ভ্যালুআপলস রয়েছে। সি # তে তাদের আরও ভাল সিনট্যাক্স রয়েছে এবং তারা মনে হয় গেটহ্যাশকোড দ্বিগুণ দ্রুত গতিবেগ হিসাবে করেছেন - gist.github.com/ljw1004/61bc96700d0b03c17cf83dbb51437a69
লুসিয়ান উইশিক

4
@ লুসিয়ান উইশিক আপনাকে ধন্যবাদ, আমি তাদের উল্লেখ করার জন্য উত্তর আপডেট করেছি।
এল্ড্রিচ কনড্রাম

22

আমি যে সর্বোত্তম উপায়টি ভাবতে পারি তা হ'ল সংগ্রহের সাথে কাজ করার সময় গতি এবং নির্ভুলতা নিশ্চিত করার জন্য একটি কম্পোজিটকি স্ট্রাক্ট তৈরি করা এবং গেটহ্যাশকোড () এবং সমতুল্য () পদ্ধতিগুলি ওভাররাইড করা নিশ্চিত করা:

class Program
{
    static void Main(string[] args)
    {
        DateTime firstTimestamp = DateTime.Now;
        DateTime secondTimestamp = firstTimestamp.AddDays(1);

        /* begin composite key dictionary populate */
        Dictionary<CompositeKey, string> compositeKeyDictionary = new Dictionary<CompositeKey, string>();

        CompositeKey compositeKey1 = new CompositeKey();
        compositeKey1.Int1 = 11;
        compositeKey1.Int2 = 304;
        compositeKey1.DateTime = firstTimestamp;

        compositeKeyDictionary[compositeKey1] = "FirstObject";

        CompositeKey compositeKey2 = new CompositeKey();
        compositeKey2.Int1 = 12;
        compositeKey2.Int2 = 9852;
        compositeKey2.DateTime = secondTimestamp;

        compositeKeyDictionary[compositeKey2] = "SecondObject";
        /* end composite key dictionary populate */

        /* begin composite key dictionary lookup */
        CompositeKey compositeKeyLookup1 = new CompositeKey();
        compositeKeyLookup1.Int1 = 11;
        compositeKeyLookup1.Int2 = 304;
        compositeKeyLookup1.DateTime = firstTimestamp;

        Console.Out.WriteLine(compositeKeyDictionary[compositeKeyLookup1]);

        CompositeKey compositeKeyLookup2 = new CompositeKey();
        compositeKeyLookup2.Int1 = 12;
        compositeKeyLookup2.Int2 = 9852;
        compositeKeyLookup2.DateTime = secondTimestamp;

        Console.Out.WriteLine(compositeKeyDictionary[compositeKeyLookup2]);
        /* end composite key dictionary lookup */
    }

    struct CompositeKey
    {
        public int Int1 { get; set; }
        public int Int2 { get; set; }
        public DateTime DateTime { get; set; }

        public override int GetHashCode()
        {
            return Int1.GetHashCode() ^ Int2.GetHashCode() ^ DateTime.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (obj is CompositeKey)
            {
                CompositeKey compositeKey = (CompositeKey)obj;

                return ((this.Int1 == compositeKey.Int1) &&
                        (this.Int2 == compositeKey.Int2) &&
                        (this.DateTime == compositeKey.DateTime));
            }

            return false;
        }
    }
}

গেটহ্যাশকোডে একটি এমএসডিএন নিবন্ধ ():

http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx


আমি মনে করি না যে এটি আসলেই খুব সম্ভবত একটি অনন্য হ্যাশকোড হতে 100% নিশ্চিত certain
হানস ওলসন

এটা খুব ভাল হতে পারে! লিঙ্কযুক্ত এমএসডিএন নিবন্ধ অনুসারে, এটি গেটহ্যাশকোড () কে ওভাররাইড করার প্রস্তাবিত উপায়। তবে, যেহেতু আমি আমার প্রতিদিনের কাজে প্রচুর সংমিশ্রিত কী ব্যবহার করি না, তাই আমি নিশ্চিতভাবে বলতে পারি না।
অ্যালেন ই। Scharfenberg

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

4
এবং হ্যাঁ, সমানগুলিও মিলতে ওভাররাইড করা উচিত। এমনকি যদি আপনি গেটহ্যাশকোড () কোনও সংখ্যার জন্য 0 প্রদান করে থাকেন তবে অভিধান এখনও কাজ করবে, এটি ধীর হবে।
জেসন ক্লেবান

4
বিল্টিন টিপল টাইপ আপনার 'এইচ 1 ^ এইচ 2' এর পরিবর্তে '(এইচ 1 << 5) + এইচ 1 instead এইচ 2' হিসাবে হ্যাশ সংমিশ্রণ প্রয়োগ করে। আমার ধারণা তারা হ্যাশ থেকে দুটি বস্তু একই মানের সমান হওয়ায় প্রতিবার সংঘর্ষ এড়াতে পারে।
এল্ড্রিচ কনড্রাম

13

কেমন Dictionary<int, Dictionary<int, Dictionary<DateTime, MyClass>>> ?

এটি আপনাকে করতে দেয়:

MyClass item = MyData[8][23923][date];

4
এটি একটি আরও অনেকগুলি অবজেক্ট তৈরি করবে এবং তারপরে একটি যৌগিকরণ কাঠামো বা শ্রেণিটি তৈরি করবে। এবং দুটি স্তরের দেখার জন্য ব্যবহৃত হবে বলে ধীর হবে।
আয়ান রিংরোজ

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

9
আমার বেঞ্চমার্কিংয়ের উপর ভিত্তি করে, যা আমি 2 এবং 3 অংশের সাহায্যে চাবি দিয়ে চেষ্টা করেছি: একটি নেস্টেড ডিকশনারি সলিউশনটি একটি টিউপল কম্পোজিট কী পদ্ধতির ব্যবহারের চেয়ে 3-4 গুণ দ্রুত faster তবে, টিউপল পদ্ধতিটি অনেক সহজ / পরিশ্রমী।
রিকএল

4
@ রিকএল আমি সেই মানদণ্ডগুলি নিশ্চিত করতে পারি, আমরা আমাদের কোড-বেসে এমন একটি প্রকার ব্যবহার করি, যাকে বলা হয় CompositeDictionary<TKey1, TKey2, TValue>(ইত্যাদি) যা কেবলমাত্র উত্তরাধিকার সূত্রে প্রাপ্ত হয় Dictionary<TKey1, Dictionary<TKey2, TValue>>(বা তবে অনেকগুলি নেস্টেড ডিকশনারি প্রয়োজন হয়। গ্রাউন্ড থেকে আমাদের সম্পূর্ণ প্রকারটি বাস্তবায়ন না করেই (ব্যবহার করে প্রতারণার পরিবর্তে নেস্টেড ডিকশনারি বা কীগুলি ধারণ করার জন্য টাইপগুলি) এটি আমাদের কাছে দ্রুত পাওয়া যায়
অ্যাডাম হল্ডসওয়ার্থ

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

12

আপনি এগুলি একটি স্ট্রাক্টে সঞ্চয় করতে পারেন এবং এটি কী হিসাবে ব্যবহার করতে পারেন:

struct CompositeKey
{
  public int value1;
  public int value2;
  public DateTime value3;
}

হ্যাশ কোড পাওয়ার জন্য লিঙ্ক: http://msdn.microsoft.com/en-us/library/system.valuetype.gethashcode.aspx


আমি .NET 3.5 এ আটকেছি সুতরাং আমার কাছে অ্যাক্সেস নেই Tupleতাই এটি একটি ভাল সমাধান!
অ্যারোনা

আমি আশ্চর্য হয়েছি যে এটি আরও উত্সাহী নয়। এটি একটি সাধারণ সমাধান যা একটি টুপলের চেয়ে বেশি পঠনযোগ্য।
চিহ্নিত করুন

4
এমএসডিএন অনুসারে এটি ঠিকঠাক কাজ করে, যদি কোনও ক্ষেত্র রেফারেন্সের ধরণ না হয়, অন্যথায় এটি সাম্যের প্রতিচ্ছবি ব্যবহার করে।
গ্রেগর স্লেভেক

@ মার্ক একটি স্ট্রাক্টের সাথে সমস্যাটি হ'ল এর ডিফল্ট গেটহ্যাশকোড () বাস্তবায়ন আসলে কাঠামোর সমস্ত ক্ষেত্র ব্যবহারের গ্যারান্টি দেয় না (অভিধানের দুর্বল পারফরম্যান্সের দিকে নিয়ে যায়), যেখানে টুপলে এই ধরনের গ্যারান্টি সরবরাহ করে। আমি এটি পরীক্ষা করেছি। গোরীর বিবরণগুলির জন্য স্ট্যাকওভারফ্লো. com/ প্রশ্নগুলি / ৩৮৪১60০২/২ দেখুন ।
এল্ড্রিচ কনড্রাম

8

এখন যে ভিএস2017 / সি # 7 প্রকাশিত হয়েছে, সেরা উত্তরটি হ'ল ভ্যালুআপল:

// declare:
Dictionary<(string, string, int), MyClass> index;

// populate:
foreach (var m in myClassList) {
  index[(m.Name, m.Path, m.JobId)] = m;
}

// retrieve:
var aMyClass = index[("foo", "bar", 15)];

আমি একটি বেনামী ValueTuple সঙ্গে অভিধান ডিক্লেয়ার বেছে নেওয়া হয়েছে (string, string, int)। তবে আমি তাদের নাম দিতে পারতাম(string name, string path, int id)

নিখুঁতভাবে, নতুন ভ্যালুআপলটি টিপল এটের চেয়ে দ্রুত GetHashCodeতবে ধীর Equals। আমি মনে করি আপনার দৃশ্যের জন্য সত্যই দ্রুততম কোনটি নির্ধারণ করতে আপনার সম্পূর্ণ শেষ থেকে শেষের পরীক্ষা করা দরকার। তবে ভ্যালুআপল এর জন্য শেষ থেকে শেষের বিশেষত্ব এবং ভাষার বাক্য গঠনটি এটিকে জিতিয়ে তোলে।

// Perf from https://gist.github.com/ljw1004/61bc96700d0b03c17cf83dbb51437a69
//
//              Tuple ValueTuple KeyValuePair
//  Allocation:  160   100        110
//    Argument:   75    80         80    
//      Return:   75   210        210
//        Load:  160   170        320
// GetHashCode:  820   420       2700
//      Equals:  280   470       6800

হ্যাঁ, আমি কেবল মুখে অনামিকার ধরণের সমাধানটি ফুটিয়ে তুলতে একটি বড় পুনর্লিখন দিয়েছি (বিভিন্ন সমাবেশগুলির সাথে তৈরি বেনামের ধরণের তুলনা করতে পারি না)। ValueTuple যৌগিক অভিধান কীগুলির সমস্যার তুলনামূলকভাবে মার্জিত সমাধান বলে মনে হচ্ছে।
চতুর্দিকে

5

দুটি উপায় অবিলম্বে মনে মনে বসন্ত:

  1. কেভিন পরামর্শ অনুসারে করুন এবং এমন একটি কাঠামো লিখুন যা আপনার কী হিসাবে কাজ করবে। এই কাঠামোটি বাস্তবায়িত করতে IEquatable<TKey>এবং এর Equalsএবং GetHashCodeপদ্ধতিগুলিকে * ওভাররাইড করতে ভুলবেন না ।

  2. অভ্যন্তরীণভাবে নেস্টেড অভিধানগুলি ব্যবহার করে এমন একটি শ্রেণি লিখুন। কিছু: TripleKeyDictionary<TKey1, TKey2, TKey3, TValue>... এই শ্রেণীর অভ্যন্তরীণভাবে টাইপ একজন সদস্য হবে Dictionary<TKey1, Dictionary<TKey2, Dictionary<TKey3, TValue>>>, এবং যেমন পদ্ধতি প্রকাশ করে দেবেন this[TKey1 k1, TKey2 k2, TKey3 k3], ContainsKeys(TKey1 k1, TKey2 k2, TKey3 k3)ইত্যাদি

* Equalsপদ্ধতিটি ওভাররাইডিং কিনা তা নিয়ে একটি শব্দ প্রয়োজনীয়: যদিও এটি সত্য যে Equalsকোনও কাঠামোর জন্য পদ্ধতিটি প্রতিটি সদস্যের ডিফল্টর সাথে মূল্য নির্ধারণ করে, প্রতিচ্ছবি ব্যবহার করে এটি করে - যা অন্তর্নিহিতভাবে কার্য সম্পাদন ব্যয়কে অন্তর্ভুক্ত করে - এবং অতএব এটি খুব বেশি নয় অভিধানে কী হিসাবে ব্যবহৃত হতে বোঝার জন্য এমন কোনও কিছুর জন্য যথাযথ প্রয়োগকরণ (আমার মতে, যাইহোক)। এমএসডিএন ডকুমেন্টেশন অনুসারে ValueType.Equals:

সমান পদ্ধতির ডিফল্ট রূপায়ণটি আপত্তি এবং এই উদাহরণের সাথে সম্পর্কিত ক্ষেত্রগুলির তুলনা করতে প্রতিফলন ব্যবহার করে। পদ্ধতির কার্যকারিতা উন্নত করতে নির্দিষ্ট ধরণের সমান পদ্ধতিটি ওভাররাইড করুন এবং ধরণের সমতার ধারণাটি আরও ঘনিষ্ঠভাবে উপস্থাপন করুন।


1 সম্পর্কে, আমি আপনাকে ইক্যুয়াল এবং গেটহ্যাশকোডকে ওভাররাইড করার প্রয়োজন বলে মনে করি না, সমতার ডিফল্ট প্রয়োগটি স্বয়ংক্রিয়ভাবে সমস্ত ক্ষেত্রে সমতার জন্য যাচাই করে যা আমার মনে হয় যে এই কাঠামোর উপর ঠিক হওয়া উচিত।
হান্স ওলসন

@ho: এটা নাও হতে পারে প্রয়োজনীয় , কিন্তু আমি দৃঢ়ভাবে কোনো struct যে একটি কী হিসেবে পরিবেশন করা যাচ্ছে জন্য এমনটি পরামর্শ চাই। আমার সম্পাদনা দেখুন।
ড্যান তাও

3

কীটি যদি ক্লাসের অংশ হয় তবে ব্যবহার করুন KeyedCollection
এটি এমন এক জায়গা থেকে Dictionaryযেখানে কীটি তৈরি করা হয়েছিল।
কভার এটা অভিধান অধীনে
দো কী পুনরাবৃত্তি না Keyএবং Value
কেন একটি সুযোগ কী তে একই নয় নেওয়া Keyযেমন Value
মেমরিতে একই তথ্য নকল করতে হবে না।

কীডক্ল্যাশন ক্লাস

যৌগিক কীটি প্রকাশ করতে সূচক

    using System.Collections.ObjectModel;

    namespace IntIntKeyedCollection
    {
        class Program
        {
            static void Main(string[] args)
            {
                Int32Int32DateO iid1 = new Int32Int32DateO(0, 1, new DateTime(2007, 6, 1, 8, 30, 52));
                Int32Int32DateO iid2 = new Int32Int32DateO(0, 1, new DateTime(2007, 6, 1, 8, 30, 52));
                if (iid1 == iid2) Console.WriteLine("same");
                if (iid1.Equals(iid2)) Console.WriteLine("equals");
                // that are equal but not the same I don't override = so I have both features

                Int32Int32DateCollection int32Int32DateCollection = new Int32Int32DateCollection();
                // dont't have to repeat the key like Dictionary
                int32Int32DateCollection.Add(new Int32Int32DateO(0, 0, new DateTime(2008, 5, 1, 8, 30, 52)));
                int32Int32DateCollection.Add(new Int32Int32DateO(0, 1, new DateTime(2008, 6, 1, 8, 30, 52)));
                int32Int32DateCollection.Add(iid1);
                //this would thow a duplicate key error
                //int32Int32DateCollection.Add(iid2);
                //this would thow a duplicate key error
                //int32Int32DateCollection.Add(new Int32Int32DateO(0, 1, new DateTime(2008, 6, 1, 8, 30, 52)));
                Console.WriteLine("count");
                Console.WriteLine(int32Int32DateCollection.Count.ToString());
                // reference by ordinal postion (note the is not the long key)
                Console.WriteLine("oridinal");
                Console.WriteLine(int32Int32DateCollection[0].GetHashCode().ToString());
                // reference by index
                Console.WriteLine("index");
                Console.WriteLine(int32Int32DateCollection[0, 1, new DateTime(2008, 6, 1, 8, 30, 52)].GetHashCode().ToString());
                Console.WriteLine("foreach");
                foreach (Int32Int32DateO iio in int32Int32DateCollection)
                {
                    Console.WriteLine(string.Format("HashCode {0} Int1 {1} Int2 {2} DateTime {3}", iio.GetHashCode(), iio.Int1, iio.Int2, iio.Date1));
                }
                Console.WriteLine("sorted by date");
                foreach (Int32Int32DateO iio in int32Int32DateCollection.OrderBy(x => x.Date1).ThenBy(x => x.Int1).ThenBy(x => x.Int2))
                {
                    Console.WriteLine(string.Format("HashCode {0} Int1 {1} Int2 {2} DateTime {3}", iio.GetHashCode(), iio.Int1, iio.Int2, iio.Date1));
                }
                Console.ReadLine();
            }
            public class Int32Int32DateCollection : KeyedCollection<Int32Int32DateS, Int32Int32DateO>
            {
                // This parameterless constructor calls the base class constructor 
                // that specifies a dictionary threshold of 0, so that the internal 
                // dictionary is created as soon as an item is added to the  
                // collection. 
                // 
                public Int32Int32DateCollection() : base(null, 0) { }

                // This is the only method that absolutely must be overridden, 
                // because without it the KeyedCollection cannot extract the 
                // keys from the items.  
                // 
                protected override Int32Int32DateS GetKeyForItem(Int32Int32DateO item)
                {
                    // In this example, the key is the part number. 
                    return item.Int32Int32Date;
                }

                //  indexer 
                public Int32Int32DateO this[Int32 Int1, Int32 Int2, DateTime Date1]
                {
                    get { return this[new Int32Int32DateS(Int1, Int2, Date1)]; }
                }
            }

            public struct Int32Int32DateS
            {   // required as KeyCollection Key must be a single item
                // but you don't really need to interact with Int32Int32DateS directly
                public readonly Int32 Int1, Int2;
                public readonly DateTime Date1;
                public Int32Int32DateS(Int32 int1, Int32 int2, DateTime date1)
                { this.Int1 = int1; this.Int2 = int2; this.Date1 = date1; }
            }
            public class Int32Int32DateO : Object
            {
                // implement other properties
                public Int32Int32DateS Int32Int32Date { get; private set; }
                public Int32 Int1 { get { return Int32Int32Date.Int1; } }
                public Int32 Int2 { get { return Int32Int32Date.Int2; } }
                public DateTime Date1 { get { return Int32Int32Date.Date1; } }

                public override bool Equals(Object obj)
                {
                    //Check for null and compare run-time types.
                    if (obj == null || !(obj is Int32Int32DateO)) return false;
                    Int32Int32DateO item = (Int32Int32DateO)obj;
                    return (this.Int32Int32Date.Int1 == item.Int32Int32Date.Int1 &&
                            this.Int32Int32Date.Int2 == item.Int32Int32Date.Int2 &&
                            this.Int32Int32Date.Date1 == item.Int32Int32Date.Date1);
                }
                public override int GetHashCode()
                {
                    return (((Int64)Int32Int32Date.Int1 << 32) + Int32Int32Date.Int2).GetHashCode() ^ Int32Int32Date.GetHashCode();
                }
                public Int32Int32DateO(Int32 Int1, Int32 Int2, DateTime Date1)
                {
                    Int32Int32DateS int32Int32Date = new Int32Int32DateS(Int1, Int2, Date1);
                    this.Int32Int32Date = int32Int32Date;
                }
            }
        }
    }

এফপিআর জন্য মূল্য টাইপ ব্যবহার করার জন্য মাইক্রোসফ্ট বিশেষত এর বিরুদ্ধে প্রস্তাব দেয়।

ভ্যালুটাইপ.গেটহ্যাশকোড

Tuple প্রযুক্তিগতভাবে কোনও মান ধরণের নয় তবে একই লক্ষণ (হ্যাশের সংঘর্ষ) থেকে ভোগা হয় এবং কোনও চাবির পক্ষে ভাল প্রার্থী হয় না।


আরও সঠিক উত্তরের জন্য +1। অবাক বিস্মিত কেউ এর আগে উল্লেখ করেনি। আসলে ওপি কাঠামোটি কীভাবে ব্যবহার করতে চায় তার উপর নির্ভর করে HashSet<T>একটি উপযুক্ত IEqualityComparer<T>একটি বিকল্পও হবে। বিটিডব্লু, আমি মনে করি আপনার উত্তরগুলি ভোট আকর্ষণ করবে যদি আপনি নিজের শ্রেণীর নাম এবং অন্যান্য সদস্যের নাম পরিবর্তন করতে পারেন :)
নওফাল

2

আমি একটি বিকল্প প্রস্তাব করতে পারি - একটি বেনামি বস্তু। এটি আমরা একাধিক কী সহ গ্রুপবাই লিনকিউ পদ্ধতিতে ব্যবহার করি।

var dictionary = new Dictionary<object, string> ();
dictionary[new { a = 1, b = 2 }] = "value";

এটি দেখতে অদ্ভুত লাগতে পারে তবে আমি ট্যাপলকে চিহ্নিত করেছি GGetHashCode এবং নতুন {a = 1, b = 2} .GetHashCode পদ্ধতি এবং বেনামে থাকা অবজেক্টগুলি .NET 4.5.1 এ আমার মেশিনে জয়লাভ করে:

অবজেক্ট - 1000 চক্রের 10000 কলের জন্য 89,1732 এমএস

টিপল - 1000 চক্রের 10000 কলের জন্য 738,4475 এমএস


হ্যাঁ, এই বিকল্পটি কখনই আমার মনে ছিল না ... আপনি যদি জটিল আকারের সমন্বিত কী হিসাবে ব্যবহার করেন তবে এটি ভাল আচরণ করবে কিনা তা আমি জানি না।
গ্যাব্রিয়েল এস্পিনোজা

যদি আপনি কেবল কোনও বস্তু পাস করেন (অজ্ঞাতনামাটির পরিবর্তে) এই অবজেক্টের গেটহ্যাশকোড পদ্ধতির ফলাফল ব্যবহার করা হবে। আপনি যদি এটির মতো ব্যবহার করেন dictionary[new { a = my_obj, b = 2 }]তবে ফলাফলগুলি হ্যাশ কোডটি my_obj.GetHashCode এবং ((Int32) 2) এর মিশ্রণ হবে .GetHashCode।
মাইকেল লোগুতভ

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

এবং এই ক্ষেত্রে এটি কীভাবে গুরুত্বপূর্ণ?
মাইকেল লোগুতভ

0

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

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