Home > front end >  Dictionary with a list of ints as key where the order of the values in the list should mattor
Dictionary with a list of ints as key where the order of the values in the list should mattor

Time:03-25

Hi im trying to use a Dictionary with a list of ints as key where the order of the values in the list should mattor. so if a have somthing like this

List<int> list1 = new List<int>();
    list1.Add(1);
    list1.Add(2);
    list1.Add(3);
    List<int> list2 = new List<int>();
    list2.Add(1);
    list2.Add(2);
    list2.Add(3);
    Dictionary<List<int>,int> dictionary = new Dictionary<List<int>,int>();
    dictionary.Add(list2 , 100);

i want to be able to access the value in the dictionary with list2. So in term of functionallity i want it to work similar to

Enumerable.SequenceEqual(list1, list2)

CodePudding user response:

The easiest solution would be to just serialize the list of ints into a string.

For example:

Dictionary<string,int> dictionary = new Dictionary<string,int>();
dictionary.Add(string.Join(",", list2), 100);

You could do a less hacky thing where you define your own class which encapsulates the list and properly implements GetHashCode() and Equals(). important: You will need to be careful with this class since lists are mutable. If you insert something into the list after you have added the item to the dictionary you won't get the expected behavior:

For example:

List<int> list1 = new List<int>();
list1.Add(1);
list1.Add(2);
list1.Add(3);
MyListWrapper wrapper1 = new MyListWrapper(list1);
List<int> list2 = new List<int>();
list2.Add(1);
list2.Add(2);
list2.Add(3);
MyListWrapper wrapper2 = new MyListWrapper(list2);
Dictionary<MyListWrapper,int> dictionary = new Dictionary<MyListWrapper,int>();
dictionary.Add(wrapper1, 100);
Assert.AreEqual(100, dictionary[wrapper2]); // this will work
list1.Add(5);
list2.Add(5);
Assert.AreEqual(100, dictionary[wrapper2]); // this will NOT work

CodePudding user response:

You should build your Dictionary using the constructor accepting an IEqualityComparer.

In the implementation of that IEqualityComparer you should use SequenceEqual instead of / in addition to standard equality.

Example (on C# PlayGround):

public class IEnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        return Object.ReferenceEquals(x, y) || (x != null && y != null && x.SequenceEqual(y));
    }

    public int GetHashCode(IEnumerable<T> obj)
    {
        unchecked
        {
            return obj.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a   b);
        }
    }
}
var key1 = new List<int> { 1, 3, 5 };
var key2 = new List<int> { 2, 4, 6 };
var key3 = new List<int> { 1, 3, 5 };
var comparer = new IEnumerableComparer<int>();
var dictionary = new Dictionary<List<int>, string>(comparer);
dictionary.Add(key1, "hello");
dictionary.Add(key2, "world");
Console.WriteLine(dictionary[key3]); // prints "hello"

Info: A quick research shows that the mentioned Dictionary constructor is available since at least .NET Framework 2.0. It's available in all versions up to the most current one (at the time of writing: .NET 6).

  •  Tags:  
  • c#
  • Related