簡體   English   中英

獲取不同的列表值

[英]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上覆蓋EqualsGetHashCode

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

這是基本相同的問題的答案 ,這將有所幫助。

說明:

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<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM