尝试通过联合合并两个列表<>.仍然有重复项

本文关键字:列表 两个 合并 | 更新日期: 2023-09-27 18:33:59

我有两个列表:

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, 2, 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,对于联盟:

默认

相等比较器"默认"用于比较 实现 IEqualityComparer(Of T) 泛型的类型 接口。要比较自定义数据类型,您需要实现此 接口,并提供您自己的 GetHashCode 和 Equals 方法。 类型。

链接

由于您使用的是自定义类型,因此您需要覆盖GetHashCodeEquals或提供一个实现 IEqualityComparer 接口的对象(最好是 IEquatable ),并将其作为第二个参数提供给 Union

下面是实现此类的简单示例。

我不喜欢覆盖 Files 类等于对象和 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 Method:

如果要比较自定义数据类型的对象序列,请 >

特定于 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;
    }
}