Question

i have to cast a list to a dictionary in my app but im getting an error saying that "An item with the same key has already been added". But it is a list with more then 5k objects and i need to see wich objects are with the same key. Is there a way to do that? In the message exception i cant get it, so i thought that i can do it using a foreach or something. Any suggestions? Thanks!

EDIT:

   var targetDictionary = targetCollection.ToDictionary(k => k.Key);

This target collection is a generic IEnumerable, and the key i get from a thirdy party database so i do not have access to it. The solution is find the problematic object and tells the supplier about it.

Était-ce utile?

La solution

You can use LINQ to catch the duplicates. You can then process them as you wish.

create a dictionary that doesn't contain the duplicates

var duplicates = myList.GroupBy(x => x.SomeKey).Where(x => x.Count() > 1);

var dictionaryWithoutDups = myList
    .Except(duplicates.SelectMany(x => x))
    .ToDictionary(x => x.SomeKey);

create a dictionary that contains only the first of each duplicate

var groups = myList.GroupBy(x => x.SomeKey);

var dictionaryWithFirsts = groups.Select(x => x.First()).ToDictionary(x => x.SomeKey);

Autres conseils

var badGroups = collection.GroupBy(item => item.Key)
                          .Where(group => group.Count() > 1);

foreach (var badGroup in badGroups)
{
   Console.WriteLine("The key {0} appears {1} times.", badGroup.Key, badGroup.Count());

   forach (var badItem in badGroup)
   {
      Console.WriteLine(badItem);
   }
}

var goodItems = collection.GroupBy(item => item.Key)
                          .Where(group => group.Count() == 1)
                          .SelectMany(group => group);

foreach (var goodItem in goodItems)
{
   Console.WriteLine("The key {0} appears exactly once.", goodItem.Key);
}

var dictionary = goodItems.ToDictionary(item => item.Key);

If you want to keep the duplicates you can use .ToLookup instead. It creates a ILookup<TKey, TValue> which is basically a read-only Dictionary<TKey, IEnumerable<TValue>> where the duplicates are stored as the "value" in a collection.

If you are just looking for dups

HashSet<string> hs = new HashSet<string>();   
foreach(string s in myList) if(!hs.Add(s)) Debug.WriteLine("dup: " + s);

Or you could change hs to Dictionary if you want to process

Dictionary<string, myclass> dl = new Dictionary<string, myclass>();    
foreach(string s in myList)
{
   if(dl.ContainsKey(s)) 
   {
      Debug.WriteLine("dup: " + s);
   }
   else 
   {
      dl.Add(s, null);
   }
}

I see you accepted a LINQ answer but LINQ is not going to out perform this.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top