Get distinct list values

i have a C# application in which i’d like to get from a List of Project objects , another List which contains distinct objects.

i tried this

 List<Project> model = notre_admin.Get_List_Project_By_Expert(u.Id_user);
 if (model != null) model = model.Distinct().ToList();

The list model still contains 4 identical objects Project.

What is the reason of this? How can i fix it?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You need to define “identical” here. I’m guessing you mean “have the same contents”, but that is not the default definition for classes: the default definition is “are the same instance”.

If you want “identical” to mean “have the same contents”, you have two options:

  • write a custom comparer (IEqualityComparer<Project>) and supply that as a parameter to Distinct
  • override Equals and GetHashCode on Project

There are also custom methods like DistinctBy that are available lots of places, which is useful if identity can be determined by a single property (Id, typically) – not in the BCL, though. But for example:

if (model != null) model = model.DistinctBy(x => x.Id).ToList();

With, for example:
public static IEnumerable<TItem>
    DistinctBy<TItem, TValue>(this IEnumerable<TItem> items,
    Func<TItem, TValue> selector)
{
    var uniques = new HashSet<TValue>();
    foreach(var item in items)
    {
        if(uniques.Add(selector(item))) yield return item;
    }
}

Method 2

var newList = 
(
from x in model
select new {Id_user= x.Id_user}
).Distinct();

or you can write like this
var list1 = model.DistinctBy(x=> x.Id_user);

Method 3

How do you define identical? You should override Equals in Project with this definition (if you override Equals also override GetHashCode). For example:

public class Project
{
    public int ProjectID { get; set; }

    public override bool Equals(object obj)
    {
        var p2 = obj as Project;
        if (p2 == null) return false;
        return this.ProjectID == m2.ProjectID;
    }

    public override int GetHashCode()
    {
        return ProjectID;
    }
}

Otherwise you are just checking reference equality.

Method 4

The object’s reference aren’t equal. If you want to be able to do that on the entire object itself and not just a property, you have to implement the IEqualityComparer or IEquatable<T>.

Method 5

Check this example: you need to use either Comparator or override Equals()

class Program
{
    static void Main( string[] args )
    {
        List<Item> items = new List<Item>();
        items.Add( new Item( "A" ) );
        items.Add( new Item( "A" ) );
        items.Add( new Item( "B" ) );
        items.Add( new Item( "C" ) );

        items = items.Distinct().ToList();
    }
}

public class Item
{
    string Name { get; set; }
    public Item( string name )
    {
        Name = name;
    }

    public override bool Equals( object obj )
    {
        return Name.Equals((obj as Item).Name);
    }
    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}

Method 6

Here’s an answer from basically the same question that will help.

Explanation:

The Distinct() method checks reference equality for reference types. This means it is looking for literally the same object duplicated, not different objects which contain the same values.

Credits to @Rex M.

Method 7

Isn’t simpler to use one of the approaches shown below 🙂 ?
You can just group your domain objects by some key and select FirstOrDefault like below.

More interesting option is to create some Comparer adapter that takes you domain object and creates other object the Comparer can use/work with out of the box. Base on the comparer you can create your custom linq extensions like in sample below. Hope it helps 🙂

[TestMethod]
    public void CustomDistinctTest()
    {
        // Generate some sample of domain objects
        var listOfDomainObjects = Enumerable
                                    .Range(10, 10)
                                    .SelectMany(x => 
                                        Enumerable
                                        .Range(15, 10)
                                        .Select(y => new SomeClass { SomeText = x.ToString(), SomeInt = x + y }))
                                    .ToList();

        var uniqueStringsByUsingGroupBy = listOfDomainObjects
                                        .GroupBy(x => x.SomeText)
                                        .Select(x => x.FirstOrDefault())
                                        .ToList();

        var uniqueStringsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeText).ToList();
        var uniqueIntsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeInt).ToList();

        var uniqueStrings = listOfDomainObjects
                                .Distinct(new EqualityComparerAdapter<SomeClass, string>(x => x.SomeText))
                                .OrderBy(x=>x.SomeText)
                                .ToList();

        var uniqueInts = listOfDomainObjects
                                .Distinct(new EqualityComparerAdapter<SomeClass, int>(x => x.SomeInt))
                                .OrderBy(x => x.SomeInt)
                                .ToList();
    }

Custom comparer adapter:
public class EqualityComparerAdapter<T, V> : EqualityComparer<T>
    where V : IEquatable<V>
{
    private Func<T, V> _valueAdapter;

    public EqualityComparerAdapter(Func<T, V> valueAdapter)
    {
        _valueAdapter = valueAdapter;
    }

    public override bool Equals(T x, T y)
    {
        return _valueAdapter(x).Equals(_valueAdapter(y));
    }

    public override int GetHashCode(T obj)
    {
        return _valueAdapter(obj).GetHashCode();
    }
}

Custom linq extension (definition of DistinctBy extension method):
// Embedd this class in some specific custom namespace
public static class DistByExt
{
    public static IEnumerable<T> DistinctBy<T,V>(this IEnumerable<T> enumerator,Func<T,V> valueAdapter)
        where V : IEquatable<V>
    {
        return enumerator.Distinct(new EqualityComparerAdapter<T, V>(valueAdapter));
    }
}

Definition of domain object used in test case:
public class SomeClass
{
    public string SomeText { get; set; }
    public int SomeInt { get; set; }

}

Method 8

List<ViewClReceive> passData = (List<ViewClReceive>)TempData["passData_Select_BankName_List"];
    passData = passData?.DistinctBy(b=>b.BankNm).ToList();

It will Works ……


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x