Frage

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.

War es hilfreich?

Lösung

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);

Andere Tipps

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top