我需要一个关于如何基于2个关键id值合并可能超过2个列表的建议。 我有一个MyType列表,其中MyType包含id1,id2,值字段。我会得到这些列表的随机数(假设数量为n),我希望将它们合并并形成一个新列表。新列表应该是这样的 Id1,id2,value [n]的列表...如果id1,id2在其余列表中匹配,则应将它们添加到值[],否则将添加空值。
例如:
List1 :- new list ({id1,id2,”Val1”},{id3,id4,”Val2”});
List2 :- new list ({id1,id2,”Val3”},{id3,id5,”Val4”}, {id6,id4,”Val5”});
List3 :- new list ({id1,id2,”Val4”},{id3,id4,”Val7”},{id6,id7,”Val8”},{id6,id4,”Val9”});
合并后,新列表应包含:
MergeIist:- {id1,id2,[“Val1”,”val3”,”val4”]},{id3,id4,[“Val2”,NULL,”Val7”]},{id3,id5,[NULL,”Val4”,NULL]},
{ id6,id4,[NULL,”Val5”,”Val9”] },{ id6,id7,[NULL,NULL,”Val8”] }
我有一个算法,但这非常昂贵,如为列表中的每个条目添加一个标记,如“已处理”,并比较列表中的所有条目和合并。有没有一种聪明的方法来处理这个问题?
答案 0 :(得分:1)
这是一个LINQ解决方案;我不能说它的效率如何......
var list1 = new [] { new MyType {Id1="1", Id2="2", Value="Val1" }, new MyType {Id1="3", Id2="4", Value="Val2" }};
var list2 = new [] { new MyType {Id1="1", Id2="2", Value="Val3" }, new MyType {Id1="3", Id2="5", Value="Val4" }, new MyType {Id1="6", Id2="4", Value="Val5" }};
var list3 = new [] { new MyType {Id1="1", Id2="2", Value="Val4" }, new MyType {Id1="3", Id2="4", Value="Val7" }, new MyType {Id1="6", Id2="7", Value="Val8" }, new MyType {Id1="6", Id2="4", Value="Val9" }};
var lists = new [] {list1, list2, list3};
var ids = lists.SelectMany(t => t).
Select(t => new { Id1=t.Id1, Id2=t.Id2 }).
Distinct().ToList();
var output = ids.Select(id => new MyTypeConsolidated {
Id1=id.Id1, Id2=id.Id2, Value =
lists.Select(ls => {
var match = ls.FirstOrDefault(t => t.Id1 == id.Id1 && t.Id2 == id.Id2);
return match == null ? null : match.Value;
}).ToArray()
});
使用的类:
class MyType {
public string Id1;
public string Id2;
public string Value;
}
class MyTypeConsolidated {
public string Id1;
public string Id2;
public string[] Value;
}
输出:
1, 2, [Val1,Val3,Val4]
3, 4, [Val2,NULL,Val7]
3, 5, [NULL,Val4,NULL]
6, 4, [NULL,Val5,Val9]
6, 7, [NULL,NULL,Val8]
这是一个有效的Fiddle。
答案 1 :(得分:1)
这是一个替代方案 - 它与Blorgbeard的答案非常相似,但我怀疑在处理更大的列表时这会更有效。
我开始是这样的,就像这样:
var list1 = new [] { new { X = "1", Y = "2", Value = "Val1" }, new { X = "3", Y = "4", Value = "Val2" }};
var list2 = new [] { new { X = "1", Y = "2", Value = "Val3" }, new { X = "3", Y = "5", Value = "Val4" }, new { X = "6", Y = "4", Value = "Val5" }};
var list3 = new [] { new { X = "1", Y = "2", Value = "Val4" }, new { X = "3", Y = "4", Value = "Val7" }, new { X = "6", Y = "7", Value = "Val8" }, new { X = "6", Y = "4", Value = "Val9" }};
var lists = new [] { list1, list2, list3 };
var ids =
lists
.SelectMany(z => z)
.Select(z => new { z.X, z.Y })
.Distinct()
.ToArray();
但后来我创建了一个查找词典:
var lookups =
lists
.Select((z, n) => new
{
Index = n,
Lookup = z.ToLookup(w => new { w.X, w.Y }, w => w.Value),
})
.ToDictionary(z => z.Index, z => z.Lookup);
最后,我产生了输出:
var output =
from id in ids
select new
{
id.X,
id.Y,
Values =
lists
.SelectMany((_, n) => lookups[n][new { id.X, id.Y }].DefaultIfEmpty(null))
.ToArray(),
};
输出是按要求的。
答案 2 :(得分:0)
我认为您需要创建一个字典来存储发生的id1值列表,然后对于每个值都有一个字典,该字典存储发生的id2值列表,最后是一个字符串列表组合。所以像这样......
Dictionary<int, Dictionary<int, List<string>>> x;
现在,您枚举每个源列表中的每个三元组,然后执行第一个id的查找,第二个id的查找以及最后添加到字符串列表。完成后,您将通过处理上述数据结构的三个级别来生成新列表。