给出这样的记录集合:
string ID1;
string ID2;
string Data1;
string Data2;
// :
string DataN
最初Data1..N为null,对于这个问题几乎可以忽略。 ID1& ID2都唯一地标识记录。所有记录都有ID2;有些还会有ID1。给定一个ID2,有一个(耗时)方法来获得它的相应ID1。给定一个ID1,有一个(耗时)方法来获取记录的Data1..N。我们的最终目标是尽快为所有记录填写Data1..N。
我们的直接目标是(尽快)消除列表中的所有重复项,并为其保留更多信息。
例如,如果Rec1 == {ID1 =“ABC”,ID2 =“XYZ”},并且Rec2 = {ID1 = null,ID2 =“XYZ”},则这些是重复的,但是我们必须特别删除Rec2并保留Rec1。
最后一项要求消除了删除Dups(例如HashSet)的标准方法,因为他们认为“复制”的两面都可以互换。
答案 0 :(得分:4)
如何将原始列表分成3个包含所有数据的列表,包含ID1的列表和只包含ID2的列表。
然后做:
var unique = allData.Concat(id1Data.Except(allData))
.Concat(id2Data.Except(id1Data).Except(allData));
仅基于ID2定义了相等。
我怀疑有更有效的表达方式,但据我所知,基本理念是合理的。将初始列表拆分为三个只是使用GroupBy
(然后在每个组上调用ToList
以避免重复查询)。
编辑:可能更好的想法:像以前一样拆分数据,然后执行:
var result = new HashSet<...>(allData);
result.UnionWith(id1Data);
result.UnionWith(id2Data);
我相信 UnionWith
保留现有的元素,而不是用新的但相同的元素覆盖它们。另一方面,这没有明确规定。它定义明确很好......
(同样,要么基于ID2使你的类型实现相等,要么使用相等比较器来创建哈希集。)
答案 1 :(得分:0)
几个月前我遇到过类似的问题。
尝试这样的事情......
public static List<T> RemoveDuplicateSections<T>(List<T> sections) where T:INamedObject
{
Dictionary<string, int> uniqueStore = new Dictionary<string, int>();
List<T> finalList = new List<T>();
int i = 0;
foreach (T currValue in sections)
{
if (!uniqueStore.ContainsKey(currValue.Name))
{
uniqueStore.Add(currValue.Name, 0);
finalList.Add(sections[i]);
}
i++;
}
return finalList;
}
答案 2 :(得分:0)
这可能闻起来很多,但我认为如果确保两个比较的对象出现相同,那么LINQ-distinct仍然适用于你。以下比较器将执行此操作:
private class Comp : IEqualityComparer<Item>
{
public bool Equals(Item x, Item y)
{
var equalityOfB = x.ID2 == y.ID2;
if (x.ID1 == y.ID1 && equalityOfB)
return true;
if (x.ID1 == null && equalityOfB)
{
x.ID1 = y.ID1;
return true;
}
if (y.ID1 == null && equalityOfB)
{
y.ID1 = x.ID1;
return true;
}
return false;
}
public int GetHashCode(Item obj)
{
return obj.ID2.GetHashCode();
}
}
然后你可以在列表上使用它......
var l = new[] {
new Item { ID1 = "a", ID2 = "b" },
new Item { ID1 = null, ID2 = "b" } };
var l2 = l.Distinct(new Comp()).ToArray();
答案 3 :(得分:0)
records.GroupBy(r => r, new RecordByIDsEqualityComparer())
.Select(g => g.OrderByDescending(r => r, new RecordByFullnessComparer()).First())
或者如果要合并记录,则Aggregate
代替OrderByDescending/First
。