簡體   English   中英

嘗試通過Union合並兩個列表<>。 仍然有重復

[英]Attempting to merge two Lists<> via Union. Still have duplicates

我有兩個列表:

List<L1>, List<L2>

L1 = { detailId = 5, fileName = "string 1" }{ detailId = 5, fileName = "string 2" }
L2 = { detailId = 5, fileName = "string 2" }{ detailId = 5, fileName = "string 3" }

我希望將它們組合在一起,而不是重復:

List<L3>

L1 = { detailId = 5, fileName = "string 1" }{ detailId = 5, fileName = "string 2" }{ detailId = 5, fileName = "string 3" }

我試過了:

L1.Union(L2).ToList();
L1.Concat(L2).Distinct().ToList();

但兩者都返回重復(1,2,3,3)。

不知道我錯過了什么。

編輯這是方法。 它需要一個列表並從分隔的字符串創建另一個列表,並嘗試將它們組合在一起。

private List<Files> CombineList(int detailId, string fileNames)
{
    List<Files> f1 = new List<Files>();
    List<Files> f2 = new List<Files>();
    f1 = GetFiles(detailId, false);
    if (f1[0].fileNames != "")
    {
        string[] names = fileNames.Split('|');
        for (int i = 0; i < names.Length; i++)
        {
            Files x = new Files();
            x.detailId = detailId;
            x.fileNames = names[i];
            f2.Add(x);
        }
        List<Files> f3 = f1.Union(f2).ToList();
    }
    return f3;

}

來自MSDN,對於Union:

默認的相等比較器Default用於比較實現IEqualityComparer(Of T)泛型接口的類型的值。 要比較自定義數據類型,您需要實現此接口並為該類型提供自己的GetHashCode和Equals方法。

鏈接

由於您使用自定義類型,因此您需要覆蓋GetHashCodeEquals或者提供實現IEqualityComparer接口的對象(最好是IEquatable )並將其作為第二個參數提供給Union

這是一個實現這樣一個類的簡單例子。

我不喜歡覆蓋Files類equals對象和getHashCode,因為你干擾了對象。 讓另一個對象執行此操作並將其傳入。這樣如果以后遇到問題,只需將其交換出來並傳遞另一個IEqualityComparer這是一個可以測試的示例

public void MainMethod()
{
    List<Files> f1 = new List<Files>() { new Files() { detailId = 5, fileName = "string 1" }, new Files() { detailId = 5, fileName = "string 2" } };
    List<Files> f2 = new List<Files>() { new Files() { detailId = 5, fileName = "string 2" }, new Files() { detailId = 5, fileName = "string 3" } };

    var f3 = f1.Union(f2, new FilesComparer()).ToList();
    foreach (var f in f3)
    {
    Console.WriteLine(f.detailId + " " + f.fileName);
    }

}

public class Files
{
    public int detailId;
    public string fileName;
}

public class FilesComparer : IEqualityComparer<Files>
{
    public bool Equals(Files x, Files y)
    {
        return x.fileName == y.fileName;
    }

    public int GetHashCode(Files obj)
    {
        return obj.fileName.GetHashCode();
    }
}

如果你的元素沒有實現某種比較接口(Object.Equals,IEquatable,IComparable等),那么它們之間的任何相等性測試都將涉及ReferenceEquals ,其中兩個不同的對象是兩個不同的對象,即使它們的所有成員都包含相同的值。

如果要合並對象列表,則需要為等式比較定義一些條件。 以下示例演示了這一點:

class MyModelTheUniqueIDComparer : IEqualityComparer<MyModel>
{
    public bool Equals(MyModel x, MyModel y)
    {
        return x.SomeValue == y.SomeValue && x.OtherValue == y.OtherValue;
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public int GetHashCode(MyModel myModel)
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 31 + myModel.SomeValue.GetHashCode();
            hash = hash * 31 + myModel.OtherValue.GetHashCode();
            return hash;
        }
    }
}

然后你可以打電話來得到結果:

var result = q1.Union(q2, new MyModelTheUniqueIDComparer());

來自MSDN Enumerable.Union方法

如果要比較自定義數據類型的對象序列,則必須在類中實現IEqualityComparer <T>泛型接口。

特定於Files類的示例實現,以便在合並兩個自定義類型集合時, Union可以正常工作:

public class Files : IEquatable<Files>
{
    public string fileName { get; set; }
    public int detailId { get; set; }

    public bool Equals(Files other)
    {

        //Check whether the compared object is null. 
        if (Object.ReferenceEquals(other, null)) return false;

        //Check whether the compared object references the same data. 
        if (Object.ReferenceEquals(this, other)) return true;

        //Check whether the products' properties are equal. 
        return detailId.Equals(other.detailId) && fileName.Equals(other.fileName);
    }

    // If Equals() returns true for a pair of objects  
    // then GetHashCode() must return the same value for these objects. 

    public override int GetHashCode()
    {

        //Get hash code for the fileName field if it is not null. 
        int hashFileName = fileName == null ? 0 : fileName.GetHashCode();

        //Get hash code for the detailId field. 
        int hashDetailId = detailId.GetHashCode();

        //Calculate the hash code for the Files object. 
        return hashFileName ^ hashDetailId;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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