Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary of string array lookup

I am working with a list of dictionaries containing string arrays. The dictionaries are defined/filled via a loop over a DataTable. In the following code test evaluates to false (twice), can somebody tell me why?

List<Dictionary<string[], int>> mydix = new List<Dictionary<string[], int>>();

mydix.Add(new Dictionary<string[], int>()); 
mydix.Add(new Dictionary<string[], int>()); 
mydix.Add(new Dictionary<string[], int>()); 

string[] s = {"tree"};
mydix[1].Add(s, 1);
bool test = mydix[1].ContainsKey(s); // This evaluates to true, which I understand
var entry= mydix[1][s]; // This is 1

DataTable dt=new DataTable();
dt.Columns.Add("test");
dt.Rows.Add(new string[] {"key"});            
mydix[2].Add(dt.Rows[0].ItemArray.Select(x => x.ToString()).ToArray(), 2);
test = mydix[2].ContainsKey(new string[] { "key" }); // Why does this evaluate to false?

// Here is an example with an array with two elements
DataTable dt2 = new DataTable(); 
dt2.Columns.Add("test");
dt2.Columns.Add("test2");    
string[] t={"tree1","tree2"}; 
dt2.Rows.Add(t);
mydix[0].Add(dt2.Rows[0].ItemArray.Select(x => x.ToString()).ToArray(), 3);
test = mydix[0].ContainsKey(t); // Why does this evaluate to false? 
like image 923
user2546346 Avatar asked Jan 28 '26 11:01

user2546346


1 Answers

The problem is that the string array you are using as the key to the dictionary does object comparison, not content comparison.

In order to support this type of data as a key, the easiest solution is to use an IEqualityComparer.

First, create the comparer (this is a sample; yours will need additional sanity checking and logic):

    private class ArrayComparer : IEqualityComparer<string[]>
    {
        public bool Equals(string[] item1, string[] item2)
        {
            if (item1[0] == item2[0])
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public int GetHashCode(string[] item)
        {
            return item[0].GetHashCode();
        }

Then, change the instantiation of your dictionaries to use this new comparer:

    mydix.Add(new Dictionary<string[], int>(new ArrayComparer()));
    mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 
    mydix.Add(new Dictionary<string[], int>(new ArrayComparer())); 

Once you have done this, both tests will return true.

like image 148
competent_tech Avatar answered Jan 30 '26 00:01

competent_tech