获取不同的列表值
我有一个C#应用程序,我想从一个Project对象列表,另一个包含不同对象的List。
我试过这个
List model = notre_admin.Get_List_Project_By_Expert(u.Id_user); if (model != null) model = model.Distinct().ToList();
列表模型仍包含4个相同的对象Project
。
这是什么原因? 我该如何解决?
你需要在这里定义“相同”。 我猜你的意思是“具有相同的内容”,但这不是类的默认定义:默认定义是“是同一个实例”。
如果您希望“相同”表示“具有相同的内容”,则有两种选择:
- 编写自定义比较器(
IEqualityComparer
)并将其作为参数提供给Distinct
- 在
Project
上覆盖Equals
和GetHashCode
还有像DistinctBy
这样的自定义方法可用于很多地方,如果标识可以由单个属性(通常为Id
)确定,则这种方法很有用 – 但不是在BCL中。 但是例如:
if (model != null) model = model.DistinctBy(x => x.Id).ToList();
例如:
public static IEnumerable DistinctBy(this IEnumerable items, Func selector) { var uniques = new HashSet(); foreach(var item in items) { if(uniques.Add(selector(item))) yield return item; } }
var newList = ( from x in model select new {Id_user= x.Id_user} ).Distinct();
或者你可以写这样的
var list1 = model.DistinctBy(x=> x.Id_user);
你如何定义相同的? 您应该使用此定义覆盖Project
Equals
(如果重写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; } }
否则你只是检查参考相等性 。
对象的引用不相等。 如果您希望能够在整个对象本身而不仅仅是属性上执行此操作,则必须实现IEqualityComparer或IEquatable
检查此示例:您需要使用Comparator或覆盖Equals()
class Program { static void Main( string[] args ) { List- items = new List
- (); 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(); } }
这是基本相同的问题的答案 ,这将有所帮助。
说明:
Distinct()方法检查引用类型的引用相等性。 这意味着它在字面上寻找相同的对象,而不是包含相同值的不同对象。
致@Rex M.的学分
使用下面显示的方法之一是不是更简单:)? 您可以通过某个键对域对象进行分组,然后选择FirstOrDefault,如下所示。
更有趣的选择是创建一些Comparer适配器,它接收域对象并创建Comparer可以使用/开箱即用的其他对象。 基于比较器,您可以创建自定义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(x => x.SomeText)) .OrderBy(x=>x.SomeText) .ToList(); var uniqueInts = listOfDomainObjects .Distinct(new EqualityComparerAdapter(x => x.SomeInt)) .OrderBy(x => x.SomeInt) .ToList(); }
自定义比较适配器:
public class EqualityComparerAdapter : EqualityComparer where V : IEquatable { private Func _valueAdapter; public EqualityComparerAdapter(Func 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 DistinctBy(this IEnumerable enumerator,Func valueAdapter) where V : IEquatable { return enumerator.Distinct(new EqualityComparerAdapter(valueAdapter)); } }
测试用例中使用的域对象的定义:
public class SomeClass { public string SomeText { get; set; } public int SomeInt { get; set; } }
List passData = (List )TempData["passData_Select_BankName_List"]; passData = passData?.DistinctBy(b=>b.BankNm).ToList();
它会工作……