我想知道是否可以(或者,如果它已经完成)确保保留第一个IEnumerable中的项目 - 而来自另一个IEnumerable的并集的重复项将被丢弃。
例如:
using System.Collections.Generic;
using System.Linq;
namespace MyApp.ExampleStuff
{
public class SomeDto
{
string name {get; set;}
int classId {get; set;}
int notComparedObject {get; set;}
}
public class test {
public void DoSomething()
{
IEnumerable<SomeDto> firstDto = new List<SomeDto>() { new SomeDto() {name = "Dave", classId = 1, notComparedObject = 12}};
IEnumerable<SomeDto> secondDto = new List<SomeDto>() { new SomeDto() {name = "Dave", classId = 1, notComparedObject = 16}, new SomeDto() {name = "Brad", classId = 1, notComparedObject = 77}};
var result = GetUnionedLists(firstDto, secondDto);
}
public ILookup<SomeDto> GetUnionedLists (IEnumerable<SomeDto> dtoA, IEnumerable<SomeDto> dtoB)
{
return dtoA.Union(dtoB, new SomeDtoComparer()).ToLookUp(x => x.classId);
}
}
public class SomeDtoComparer : IEqualityComparer<SomeDto>
{
public bool Equals(SomeDto SomeDtoA, SomeDto SomeDtoB)
{
if (SomeDtoA == null && SomeDtoB == null)
{
return true;
} else if (SomeDtoA == null || SomeDtoB == null)
{
return false;
}
return (SomeDtoA.Name == SomeDtoB.Name && SomeDtoA.classId == SomeDtoB.classId);
}
public int GetHashCode(SomeDto SomeDtoX)
{
int hashName = SomeDtoX.Name == null ? 0 : SomeDtoX.Name.GetHashCode();
int hashClassId = SomeDtoX.classId == null ? 0 : SomeDtoX.classId.GetHashCode();
return hashName ^ hashClassId;
}
}
}
如果运行 - 我希望DoSomething()中的结果值是一个Lookup,它只包含classId“1”下面的someDto:
SomeDto() {name = "Dave", classId = 1, notComparedObject = 12}
SomeDto() {name = "Brad", classId = 1, notComparedObject = 77}
正如你所看到的,如果“Name”和“classId”是相同的 - 结果被认为是Equal,然后我想保留原始IEnumerable中的项目,并丢弃“duplicate” - 在此案例是:
SomeDto() {name = "Dave", id = 1, notComparedObject = 16}
如果结果是这样的 - 它会被认为是错误的(因为第二个Enumerable中的项目放在结果的第一位):
SomeDto() {name = "Brad", classId = 1, notComparedObject = 77}
SomeDto() {name = "Dave", classId = 1, notComparedObject = 12}
答案 0 :(得分:1)
我认为您可以使用MoreLinq库中提供的FullJoin函数(在NuGet上提供)来实现此目的。
https://morelinq.github.io/3.0/ref/api/html/M_MoreLinq_MoreEnumerable_FullJoin__3_1.htm
示例:
public ILookup<SomeDto> GetUnionedLists (IEnumerable<SomeDto> dtoA, IEnumerable<SomeDto> dtoB)
{
return dtoA
.FullJoin(dtoB,
e => e,
first => first,
second => second,
(first, second) => first,
new SomeDtoComparer())
.ToLookUp(x => x.classId);
}
答案 1 :(得分:1)
Enumerable.Union
方法已按照您所描述的顺序生成项目。它写在docs
当枚举此方法返回的对象时,Union 按顺序枚举第一个和第二个,并产生尚未产生的每个元素。
另一方面,Lookup
类型以及IGrouping
接口不对元素顺序提供任何保证(看起来ToLookup
的当前实现保持原始顺序,但这可能更改)。所以,如果真的很重要,你应该添加一些额外的逻辑 - 比如使用自定义类型而不是Lookup
,为它添加索引和排序的自定义属性,或者可能使用GroupBy
,这确保了顺序正如docs中所述。
IGrouping对象的生成顺序基于生成每个IGrouping的第一个键的源中元素的顺序。分组中的元素按照生成它们的元素出现在源中的顺序产生。