Click here to Skip to main content
15,888,255 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have a List<listviewitem> which I will add later to my ListView with the .AddRange Method. The list contains duplicates because the entries are from different sources.

How do I remove duplicates from a List<listviewitem> without changing its type,
without changing the order of the elements,
with the usage of plain C# code (no external libraries) and without an extra coded loop for re-populating, deleting and checking?

I tried this which works for me, but the whole type is lost afterwards:

List<listviewitem> MyList = new List<listviewitem>();
//...here my List is being populated and contains duplicates... (Code not included)
List<string> tempvar = MyList.Select(x => x.Name).Distinct().ToList();

List<string> tempvar contains basically what I would need, but I need it as a List<listviewitem> not a List<string>. I am a beginner and all other stuff which I tried did not work for me like the Hashing and other sugggestions.

Later I perform the adding of the whole list to the listview as follows:
MylistView.AddRange(MyList.toArray());
After this call I would not check for duplicates anymore, the code must go before it.

What I have tried:

different suggestions for linq and distinct, nothing worked so far.
Posted
Updated 14-Mar-16 9:08am
v2
Comments
Sergey Alexandrovich Kryukov 21-Apr-16 21:07pm    
Why not preventing duplicates in first place, when you add items?
—SA

My first suggestion, if possible, would be to collect the list of distinct data first and then go from there to create a ListViewItem for each.

Another way:
Try using the version of .Distinct() that takes an IEqualityComparer<TSource> parameter.
Like:
C#
class LviNameComparer : IEqualityComparer<ListViewItem>
{
  // implement Equals and GetHashCode methods of the interface
  public bool Equals(ListViewItem lvi1, ListViewItem lvi2)
  {
    return ReferenceEquals(lvi1, lvi2) ||
           (lvi1 != null &&
            lvi2 != null &&
            lvi1.Name.Equals(lvi2.Name));
  }

  public int GetHashCode(ListViewItem lvi)
  {
    return lvi == null ? 
           0 :
           (lvi.Name ?? string.Empty).GetHashCode();
  }
}

List<string> tempvar = MyList.Distinct(new LviNameComparer()).ToList();
 
Share this answer
 
v2
Comments
Matt T Heffron 14-Mar-16 16:47pm    
You need the
using System.Collections.Generic;

And, of course, you cannot just put the LviNameComparer class declaration right before using it in the .Distinct(). It needs to be placed at the appropriate scope.
Matt T Heffron 14-Mar-16 17:07pm    
Oops, I forgot to remove the "static" declaration, also.
I edited the Solution.
Matt T Heffron 17-Mar-16 12:43pm    
You're welcome!
Please rate this solution as you see fit, and formally accept it if it seems appropriate. See QA FAQ
You're basically looking for a .DistinctBy(..) method, which isn't included in standard .NET but there are implementations, one of which you can find here:
GitHub - morelinq/MoreLINQ: Extensions to LINQ to Objects[^]

..which will allow you to do this:
C#
List<listviewitem> distinctItems = MyList.DistinctBy(x => x.Name).ToList();


Edit:
If you don't want to include the whole MoreLINQ-project into your solution, use just the following code and copy it into its own C#-source-file:
C#
using System;
using System.Collections.Generic;

namespace LinqExtensions
{
    public static class LinqExtensionDistinctBy
    {
        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            HashSet<TKey> keys = new HashSet<TKey>();

            foreach (TSource item in source)
            {
                if (keys.Add(keySelector(item)))
                {
                    yield return item;
                }
            }
        }
    }
}

Add a using LinqExtensions; -directive to your files where you want to use this extension method.
 
Share this answer
 
v3
Comments
[no name] 14-Mar-16 14:29pm    
that would be already an external library needed just to remove duplicates?
Sascha Lefèvre 14-Mar-16 14:57pm    
You could just copy&paste that extension method into your project :)
Sascha Lefèvre 14-Mar-16 15:12pm    
https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Sascha Lefèvre 14-Mar-16 15:19pm    
Extension methods (those with a this-keyword for the first parameter) need to be public static and need be contained in a public static class.
Sascha Lefèvre 14-Mar-16 15:22pm    
I assume you placed the method into one of your existing classes - instead, create a separate class for it, e.g.
public static class MyLinqExtensions

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900