11

我有一个 C# 应用程序,我想从一个项目List对象中获取另一个包含不同对象的列表。

我试过这个

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

列表模型仍然包含 4 个相同的对象Project

这是什么原因?我该如何解决?

4

8 回答 8

12

您需要在此处定义“相同”。我猜您的意思是“具有相同的内容”,但这不是类的默认定义:默认定义是“相同的实例”。

如果您希望“相同”表示“具有相同的内容”,您有两种选择:

  • 编写一个自定义比较器 ( IEqualityComparer<Project>) 并将其作为参数提供给Distinct
  • 覆盖EqualsGetHashCode打开Project

还有很多类似的自定义方法DistinctBy可用,如果身份可以由单个属性(Id通常)确定,这很有用 - 但不在 BCL 中。但例如:

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

例如:

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;
    }
}
于 2013-10-23T10:34:36.637 回答
7
var newList = 
(
from x in model
select new {Id_user= x.Id_user}
).Distinct();

或者你可以这样写

var list1 = model.DistinctBy(x=> x.Id_user);
于 2013-10-23T10:35:02.077 回答
5

你如何定义相同?你应该EqualsProject这个定义覆盖(如果你覆盖Equals也覆盖GetHashCode)。例如:

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

否则,您只是在检查引用相等性

于 2013-10-23T10:33:59.480 回答
4

对象的引用不相等。如果您希望能够对整个对象本身而不只是属性执行此操作,则必须实现 IEqualityComparer 或 IEquatable<T>。

于 2013-10-23T10:33:56.970 回答
3

检查此示例:您需要使用比较器或覆盖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();
    }
}
于 2013-10-23T10:35:48.700 回答
3

这是来自基本相同问题的答案,这将有所帮助。

解释:

Distinct() 方法检查引用类型的引用相等性。这意味着它实际上是在寻找重复的相同对象,而不是包含相同值的不同对象。

归功于@Rex M。

于 2013-10-23T10:35:50.870 回答
0

使用下面显示的方法之一是不是更简单:)?您可以通过某个键对域对象进行分组,然后选择 FirstOrDefault 如下所示。

更有趣的选项是创建一些比较器适配器,该适配器将您带入域对象并创建比较器可以使用/开箱即用的其他对象。基于比较器,您可以创建自定义 linq 扩展,如下面的示例所示。希望能帮助到你 :)

[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();
    }

自定义比较器适配器:

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

自定义 linq 扩展(DistinctBy 扩展方法的定义):

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

测试用例中使用的域对象的定义:

public class SomeClass
{
    public string SomeText { get; set; }
    public int SomeInt { get; set; }

}
于 2016-06-06T09:13:38.590 回答
0
List<ViewClReceive> passData = (List<ViewClReceive>)TempData["passData_Select_BankName_List"];
    passData = passData?.DistinctBy(b=>b.BankNm).ToList();

它会工作......

于 2017-12-12T10:08:34.540 回答