0

I am working on small utility and as it turns out I have to compare two dictionaries and export the data in Excel in the below format

Key dict1value dict2value

If a key is available in both the dictionaries. My output would be Key dict1value dict2value If a key is available in firstdictionary and not in second . My output would be Key dict1Value "NotAvailable" If a key is available in second dictionary but not in first . My output would be key "Not Available" dict2value.

To be more clear, The key column in Excel consists of keys from both the dictionaries.The value columns will have values depending on the availability.

Though the below code is working,I would like to know if I can optimize the performance even more. Note : Please ignore the bad naming conventions

        public void validateTwoDictionaries()
    {
        Dictionary<string, string> dict1 = new Dictionary<string, string>();
        Dictionary<string, string> dict2 = new Dictionary<string, string>();
        Dictionary<string, KeyValuePair<string, string>> complexdicts = new Dictionary<string, KeyValuePair<string, string>>();

        dict1.Add("A", "1");
        dict1.Add("B", "2");

        dict2.Add("A", "2");
        dict2.Add("C", "3");
        dict2.Add("D", "4");

        int count1 = dict1.Keys.Count;
        int count2 = dict2.Keys.Count;
        int maxcount = count2;
        if (count1 > count2)
        {
            maxcount = count1;

        }

        for (int i = 0; i < maxcount; i++)
        {
            string dict1Key = string.Empty; string dict2Key = string.Empty;
            //need to iterate both the dictionaries at one go.
            if (i < count1)
            {
                dict1Key = dict1.Keys.ElementAt(i);
            }
            if (i < count2)
            {
                dict2Key = dict2.Keys.ElementAt(i);
            }

            // do the work for first dictionary, try to decouple to reuse for the 2nd dict
            if (dict1Key != string.Empty)
            {
                if (!complexdicts.Keys.Contains(dict1Key))
                {
                    if (dict2.Keys.Contains(dict1Key))
                    {
                        // Add to the complext dictionary 
                        complexdicts.Add(dict1Key, new KeyValuePair<string, string>(dict1[dict1Key], dict2[dict1Key]));
                    }
                    else
                    {
                        complexdicts.Add(dict1Key, new KeyValuePair<string, string>(dict1[dict1Key], "Not Available"));
                    }
                }
            }



            // do the work for second dictionary

            if (dict2Key != string.Empty)
            {
                if (!complexdicts.Keys.Contains(dict2Key))
                {
                    if (dict1.Keys.Contains(dict2Key))
                    {
                        // Add to the complext dictionary 
                        complexdicts.Add(dict2Key, new KeyValuePair<string, string>(dict1[dict2Key], dict2[dict2Key]));
                    }
                    else
                    {
                        complexdicts.Add(dict2Key, new KeyValuePair<string, string>("Not Available", dict2[dict2Key]));
                    }
                }
            }
        }

dict1 and dict2 are sample dictionaries and complexdicts object is what I want to export to excel. Please let me know if I can do this in better way.

  • It's a dictionary, so the keys must be unique, naming them `"Not Available"` will do for the first, not for the ones after that. – Max Apr 17 '14 at 06:52
  • I see a problem in your description : if they are 2 values which are in dic2 but not in dic1, how will you manage that ? You can't have 2 `Not Available` keys. Do you really want a Dictionary as output, or may a Tuple be ok ? – Raphaël Althaus Apr 17 '14 at 06:52
  • I am sorry I should have been clear. The search filter is Key but not the value . – user3544055 Apr 17 '14 at 06:58
  • I would have to check if LINQ is performing better, but you can use .Concat in combination with .GroupBy to join two Dictionaries, which would be very readable and elegant. Seen here: http://stackoverflow.com/questions/10034867/c-sharp-linq-merge-two-dictionaries – ovm Apr 17 '14 at 07:14
  • I tried using linq. But I am not good with that stuff. But that link definitely helps. will check – user3544055 Apr 17 '14 at 07:21

2 Answers2

3

How about this?

Dictionary<string, string> dict1 = new Dictionary<string, string>();
Dictionary<string, string> dict2 = new Dictionary<string, string>();
Dictionary<string, KeyValuePair<string, string>> complexdicts = new Dictionary<string, KeyValuePair<string, string>>();

dict1.Add("A", "1");
dict1.Add("B", "2");

dict2.Add("A", "2");
dict2.Add("C", "3");
dict2.Add("D", "4");

var allKeys = dict1.Keys.Union(dict2.Keys);

foreach (var key in allKeys)
{
    string val1;
    if (!dict1.TryGetValue(key, out val1))
    {
        val1 = "Not Available";
    } 
    string val2;
    if (!dict2.TryGetValue(key, out val2))
    {
        val2 = "Not Available";
    }
    complexdicts.Add(key, new KeyValuePair<string, string>(val1, val2));
}
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
0

How about this?

Dictionary<string, string> dict1 = new Dictionary<string, string>();
Dictionary<string, string> dict2 = new Dictionary<string, string>();

dict1.Add("A", "1");
dict1.Add("B", "2");

dict2.Add("A", "2");
dict2.Add("C", "3");
dict2.Add("D", "4");

var allKeys = dict1.Keys.Union(dict2.Keys);

// case 1
List<Tuple<string, string, string>> unionValues = new List<Tuple<string, string, string>>();
foreach (var key in allKeys)
{
    unionValues.Add(new Tuple<string, string, string>(key, dict1.ContainsKey(key) ? dict1[key] : "N/A" , dict2.ContainsKey(key) ? dict2[key] : "N/A"));
}

// case 2
var result = (from key in allKeys
             select new Tuple<string, string, string>(key, dict1.ContainsKey(key) ? dict1[key] : "N/A", dict2.ContainsKey(key) ? dict2[key] : "N/A")).ToList();
Elyse
  • 1