I have some objects in List, let's say List<MyClass>
and MyClass has several properties. I would like to create an index of the list based on 3 properties of of MyClass. In this case 2 of the properties are int's, and one property is a datetime.
Basically I would like to be able to do something like:
Dictionary< CompositeKey , MyClass > MyClassListIndex = Dictionary< CompositeKey , MyClass >(); //Populate dictionary with items from the List<MyClass> MyClassList MyClass aMyClass = Dicitonary[(keyTripletHere)];
I sometimes create multiple dictionaries on a list to index different properties of the classes it holds. I am not sure how best to handle composite keys though. I considered doing a checksum of the three values but this runs the risk of collisions.
In a table representing students our primary key would now be firstName + lastName. Because students can have the same firstNames or the same lastNames these attributes are not simple keys. The primary key firstName + lastName for students is a composite key.
A composite key, in the context of relational databases, is a combination of two or more columns in a table that can be used to uniquely identify each row in the table. Uniqueness is only guaranteed when the columns are combined; when taken individually the columns do not guarantee uniqueness.
The composite key differs from a primary key and it is important to know how the two vary, both in syntax and usage. One can say that combining a set of multiple columns in a table, results in a primary key, as it will have a unique value in every row.
Dictionary<string, string> myDictionary = new Dictionary<string, string>(); Dictionary<string, string> secondDictionary = new Dictionary<string, string>() { {"1", "a"}, {"2", b"} }; myDictionary = myDictionary. Union(secondDictionary) . ToDictionary(kvp => kvp. Key, kvp => kvp.
You should use tuples. They are equivalent to a CompositeKey class, but the Equals() and GetHashCode() are already implemented for you.
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")];
Or using System.Linq
var myClassIndex = myClassList.ToDictionary(myObj => Tuple.Create(myObj.MyInt, myObj.MyBool, myObj.MyString)); MyClass myObj = myClassIndex[Tuple.Create(4, true, "t")];
Unless you need to customize the computation of the hash, it's simpler to use tuples.
If there are a lot of properties you want to include in the composite key, the Tuple type name can become pretty long, but you can make the name shorter by creating your own class deriving from Tuple<...>.
** edited in 2017 **
There is a new option starting with C# 7: the value tuples. The idea is the same, but the syntax is different, lighter:
The type Tuple<int, bool, string>
becomes (int, bool, string)
, and the value Tuple.Create(4, true, "t")
becomes (4, true, "t")
.
With value tuples, it also becomes possible to name the elements. Note that performances are slightly different, so you may want to do some benchmarking if they matter for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With