[英]Get distinct list values
我有我想從一個獲得C#應用程序List
項目的對象,其中包含不同對象另一個列表。
我試過這個
List<Project> model = notre_admin.Get_List_Project_By_Expert(u.Id_user);
if (model != null) model = model.Distinct().ToList();
列表模型仍包含4個相同的對象Project
。
這是什么原因? 我該如何解決?
你需要在這里定義“相同”。 我猜你的意思是“有相同的內容”,但這不是類的默認定義:默認定義是“是同一個實例”。
如果您希望“相同”表示“具有相同的內容”,則有兩種選擇:
IEqualityComparer<Project>
)並將其作為參數提供給Distinct
Project
上覆蓋Equals
和GetHashCode
還有像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;
}
}
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 <T>。
檢查此示例:您需要使用Comparator或覆蓋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();
}
}
使用下面顯示的方法之一是不是更簡單:)? 您可以通過某個鍵對域對象進行分組,然后選擇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<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; }
}
List<ViewClReceive> passData = (List<ViewClReceive>)TempData["passData_Select_BankName_List"];
passData = passData?.DistinctBy(b=>b.BankNm).ToList();
它會工作......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.