@manhng

Welcome to my blog!

Common C# Functions

November 14, 2017 15:03

Question - Find duplicate values in dictionary c#

I have dictionary and I need get duplicate values.

For example:

 Dictionary<int, List<string>> dictionary = new Dictionary<int, List<string>>();
                List<string> list1 = new List<string> { "John", "Smith" };
                List<string> list2 = new List<string> { "John", "Smith" };
                List<string> list3 = new List<string> { "Mike", "Johnson" };

                dictionary.Add(1, list1);
                dictionary.Add(2, list2);
                dictionary.Add(3, list3);

I need find all duplicate from dictionary and return max keys(collection of key) of each duplicate values. From my test dictionary I need return list with only one key = 2

Maybe I chose the wrong data structure. I would like to receive optimal algorithm

Answer

With your current structure, you're in a bit of trouble because you don't necessarily have an easy way to compare two List<string> to see if they are equal.

One way to work around this is to create a custom List<string> comparer that implements IEqualityComparer<List<string>>. However, since you have a list of strings, we also need to reorder both to ensure that we are comparing each value in the correct order. This affects the cost of your algorithm. On the other hand, if you are happy with the order of the values inside of the lists, that works just fine as well and you can avoid that cost.

public class StringListComparer : IEqualityComparer<List<string>>
{
    public bool Equals(List<string> x, List<string> y)
    {
        return CompareLists(x, y);
    }

    public int GetHashCode(List<string> obj)
    {
        return base.GetHashCode();
    }

    private static bool CompareLists(List<string> x, List<string> y)
    {
        if (x.Count != y.Count)
            return false;

        // we HAVE to ensure that lists are in same order
        // for a proper comparison
        x = x.OrderBy(v => v).ToList();
        y = y.OrderBy(v => v).ToList();

        for (var i = 0; i < x.Count(); i++)
        {
            if (x[i] != y[i])
                return false;
        }

        return true;
    }
}

Once we have our comparer, we can use it to pull out keys from subsequent duplicates, leaving the first key (per your requirement).

public List<int> GetDuplicateKeys(Dictionary<int, List<string>> dictionary)
{
    return dictionary
        .OrderBy (x => x.Key)
        .GroupBy(x => x.Value, new StringListComparer())
        .Where (x => x.Count () > 1)
        .Aggregate (
            new List<int>(),
            (destination, dict) => 
                {
                    var first = dict.FirstOrDefault();

                    foreach (var kvp in dict)
                    {
                        if (!kvp.Equals(first))
                            destination.Add(kvp.Key);
                    }

                    return destination;
                }   
        ).ToList();
}

The following test outputs keys 2 and 4.

Dictionary<int, List<string>> dictionary = new Dictionary<int, List<string>>();
dictionary.Add(1, new List<string> { "John", "Smith" });
dictionary.Add(2, new List<string> { "John", "Smith" });
dictionary.Add(3, new List<string> { "Mike", "Johnson"});
dictionary.Add(4, new List<string> { "John", "Smith" });

var result = GetDuplicateKeys(dictionary);

Question - Find duplicate values in dictionary c#

What can be the fastest way to to check the duplicate values in the dictionary and print its key?

Dictionary MyDict which is having following values,

Key Value
22 100
24 200
25 100
26 300
29 200
39 400
41 500

Example: key 22 and 25 have same values and i need to print that 22 and 25 have duplicate values.

Answer

It depends. If you have an ever changing dictionary and need to get that information only once, use this:

MyDict.GroupBy(x => x.Value).Where(x => x.Count() > 1)

However, if you have a dictionary that is more or less static and need to get this information more than once, you should not just save your data in a Dictionary but also in a ILookup with the value of the dictionary as the key and the key of the dictionary as the value:

var lookup = MyDict.ToLookup(x => x.Value, x => x.Key).Where(x => x.Count() > 1);

To print the info, you can use the following code:

foreach(var item in lookup)
{
    var keys = item.Aggregate("", (s, v) => s+", "+v);
    var message = "The following keys have the value " + item.Key + ":" + keys;
    Console.WriteLine(message);
}

Question - Convert string array to integer list

string tags = "9,3,12,43,2"
 

Answer

List<int> TagIds = tags.Split(',').Select(int.Parse).ToList();

Question - Convert string array to integer list


string sNumbers = "1,2,3,4,5";

How can I convert string array to integer list? So that I'll be able to convert string[] to IEnumerable

Answer

var numbers = sNumbers.Split(',').Select(Int32.Parse).ToList();

Categories

Recent posts