尝试通过联合合并两个列表<>.仍然有重复项
本文关键字:列表 两个 合并 | 更新日期: 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 方法。 类型。
链接
由于您使用的是自定义类型,因此您需要覆盖GetHashCode
并Equals
或提供一个实现 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;
}
}