基于2个唯一ID合并c#中的n个列表

时间:2015-02-16 03:13:29

标签: c# algorithm linq list

我需要一个关于如何基于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”] }

我有一个算法,但这非常昂贵,如为列表中的每个条目添加一个标记,如“已处理”,并比较列表中的所有条目和合并。有没有一种聪明的方法来处理这个问题?

3 个答案:

答案 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的查找以及最后添加到字符串列表。完成后,您将通过处理上述数据结构的三个级别来生成新列表。