1

My question is not duplicate as the one that you have marked is searching List and I am trying to search Dictionary.

I have a Dictionary<string, Player>.

Player is an object with the properties GameID, Index and more. My dictionary key is player's index. I want to check if dictionary contains two Players with same GameID (the index will be different for those). One way of doing this is iterating with foreach over dictionary values and use an variable which would be incremented every time it encounters certain GameID. But I was wondering if there is a way to do this by using linq? If there is, that solution would probably be better.

4
  • 2
    Looping over a list or a dictionary, what's the big difference? Commented Jun 2, 2019 at 10:36
  • Specifically: in this part of code .Values. But I got used to people who are prone to hating and giving minuses here on stackoverflow just because they understand something better then the others Commented Jun 2, 2019 at 10:41
  • Just because you are using different container class does not make your question unique. Even w/o Values property, Dictionary<string, Player> is IEnumerable<KeyValuePair<string, Player>>. And LINQ to Objects operate on IEnumerable<T> regardless of what class is implementing it (array, list, dictionary, whatever). So it really doesn't matter what is the actual collection type. The only important is the element type. Take the accepted answer from the duplicate question, replace lstNames.GroupBy(n => n) with dict.GroupBy(x => x.Value.GameID) and there you go. Commented Jun 2, 2019 at 13:20
  • @IvanStoev If there are people ready to help (and there are at least 3 of them here, based on answers) why do you have to point out it's a duplicate? You don't want to help? No problem, nobody forces you to, just move on. Commented Jun 2, 2019 at 18:34

3 Answers 3

3

Use LINQ's GroupBy and then filter groups larger than one:

var result = dict.Values
             .GroupBy(x => x.GameID)
             .Where(x => x.Count() > 1)
             .Select(g => g.First()); // Take one of the duplicates

Example


If you know the GameID to look for you can just use

var gameID = 1
var isDuplicate = dict.Values
                  .Where(x => x.GameID == gameID)
                  .Count() > 1;
Sign up to request clarification or add additional context in comments.

7 Comments

Actually, at the moment of search I know exactly which GameID I am looking for, so I guess there should be another WHERE with condition x.GameID == 1 for example? I am not sure how it should be written using linq.
@niksrb see my edit
Yes, trying it now in my code, will report soon
Why do we need to group ALL the data if we just want to find out whether there are duplicates or not ? Imagine that there are 1 000 000 records and duplicated records are records on position 1 and 10... This solution will group the whole 1M records
@Fabjan You dont know where the duplicates are... They could be 1 and 999999. As I understood, he wants to know which are the duplicates, not whether there are any.
|
2

Dictionaries, differently than Lists, provide a constant complexity to access one of its entries.

The purpose of a Dictionary is to map a Key -> Value relation where keys are unique. By using a generic index as Key, there is no advantage over a List<Player>.

Therefore, rather than answering an inefficiently formulated problem, I will provide a more efficient solution reformulating the original question.

You can find an implementation of a Multimap (dictionary with multiple keys) where you can represent a GameID-> Index relationship and count occurrences, here: multimap in .NET

Compared to the (currently) accepted answer, which has linear time complexity ( O(N) ) and grows worse and worse for larger Dictionaries or Lists, even with the optimizations within IQueryable in Linq, this provides a constant complexity.

3 Comments

Will try that right away. Just one note, keys in my dictionary ARE unique, not generic
@niksrb I edited, sharing some insight
This really is more efficient solution. I will have it in mind next time I face similar problem. Thanks!
0

suppose that we have these records:

    Dictionary<string, Player> myDic = new Dictionary<string, Player>();
    Player p1 = new Player() { GameID = 1, Index = "a" };
    Player p2 = new Player() { GameID = 2, Index = "b" };
    Player p3 = new Player() { GameID = 1, Index = "c" };
    Player p4 = new Player() { GameID = 3, Index = "d" };
    myDic.Add(p1.Index, p1);
    myDic.Add(p2.Index, p2);
    myDic.Add(p3.Index, p3);
    myDic.Add(p4.Index, p4);

You can try this:

 var duplicates = myDic.Values
                .GroupBy(x => x.GameID)
                .SelectMany(p =>
                    p.Select((j, i) => new { j.Index, j.GameID, rn = i + 1 }))
                .Where(x => x.rn > 1).ToList();

            foreach (var dups in duplicates)
            {
                Console.WriteLine($"record with GameId: {dups.GameID} at Index: {dups.Index} is duplicate!");
            }

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.