LINQ合并2个列表,保持顺序和原点

时间:2019-01-14 03:24:59

标签: c# list linq merge

在这里,我有2个相同对象类型的列表。

object = {id: xxx, ...} // attribute "id" is used to find the identical obj

List oldSet = [old1, old2, old3];
List newSet = [new2, new3, new4];

// old2 = {id= 2, result = 5, ...}
// new2 = {id= 2, result = 1, ...}
// expected result = {oldSet: old2; newSet: new2}

我想合并两个列表,同时还要保留列表的来源。

预期结果如下:

List mergedSet = [{old1, null}, {old2, new2}, {old3, new3}, {null, new4}];

我正在考虑使用LINQ C#,但是卡在某个地方。

请告知。

谢谢! :)

5 个答案:

答案 0 :(得分:1)

以下是使用Linq完成您想要的代码。它基本上遍历所有旧列表,并通过从新列表中查找匹配项来将对添加到合并列表中(如果找不到匹配项,则将vector<string> keyword1; vector<string> keyword2; 添加为第二项)。然后,它遍历新列表中的其余项目,并为第一个项目添加null。它选择具有两个属性的动态类型:nullOldSet,因此您知道每个项目的来源。

合并代码很简单:

NewSet

这基于以下物品类别:

var mergedSet = oldSet.Select(o =>
    new {OldSet = o, NewSet = newSet.FirstOrDefault(n => n.id == o.id)})
    .Concat(newSet.Where(n => oldSet.All(o => o.id != n.id)).Select(n =>
        new {OldSet = (Item) null, NewSet = n}));

我们创建列表:

class Item
{
    public int id { get; set; }
    public string result { get; set; }
    public override string ToString()
    {
        return $"{result}{id}";
    }
}

运行合并代码(第一个代码段),然后显示结果:

List<Item> oldSet = new List<Item>
{
    new Item {id = 1, result = "old"},
    new Item {id = 2, result = "old"},
    new Item {id = 3, result = "old"},
};

List<Item> newSet = new List<Item>
{
    new Item {id = 2, result = "new"},
    new Item {id = 3, result = "new"},
    new Item {id = 4, result = "new"},
};

输出

![enter image description here

答案 1 :(得分:0)

尝试这样的事情:

            List<string> oldSet = new List<string>() {"old1", "old2", "old3"};
            List<string> newSet = new List<string>() {"new2", "new3", "new4"};

            var results = oldSet.Select((x,i) => new { oldSet = x, newSet = newSet[i]}).ToList();

答案 2 :(得分:0)

您可以不加入两个列表。我编辑了答案,因为您实际上需要离开两次连接,并集并应用一个select来获取oldSet = null且没有重复的情况。

    var mergedSet = (from o in oldSet
                     join n in newSet on o.id equals n.id into ns
                     from n in ns.DefaultIfEmpty()
                     select new { OldSet = o, NewSet = n })
                    .Union(from n in newSet
                           join o in oldSet on n.id equals o.id into os
                           from o in os.DefaultIfEmpty()
                           select new { OldSet = o, NewSet = n })
                    .Distinct();

答案 3 :(得分:0)

可能有些大材小用,但是如果您真的想使用LINQ

List<Item> oldSet = new List<Item>
{
    new Item {id = 1, result = "old"},
    new Item {id = 2, result = "old"},
    new Item {id = 3, result = "old"},
};

List<Item> newSet = new List<Item>
{
    new Item {id = 2, result = "new"},
    new Item {id = 3, result = "new"},
    new Item {id = 4, result = "new"},
};

var resultL = oldSet.GroupJoin(
          newSet, 
          o => o.id,
          n => n.id,
          (o,n) => new { Old = o, New = n })
    .SelectMany(
          n => n.New.DefaultIfEmpty(),
          (o,n) => new Tuple<Item,Item>(o.Old,n));


 var resultR= newSet.GroupJoin(
          oldSet, 
          n => n.id,
          o=> o.id,
          (n,o) => new { Old = o, New = n })
    .SelectMany(
          o=> o.Old.DefaultIfEmpty(),
          (n,o) => new Tuple<Item,Item>(o,n.New));

var result = resultL.Union(resultR).Distinct();

答案 4 :(得分:0)

在这种情况下,您必须使用两个GroupJoinUnion的结果。 看下面的代码:

var res1 = oldSet.GroupJoin(newSet, o => o, k => k, (x, y) => { var yy = y.FirstOrDefault(); return new { X = x, Y = yy }; });
var res2 = newSet.GroupJoin(oldSet, o => o, k => k, (x, y) => { var yy = y.FirstOrDefault(); return new { X = yy, Y = x }; });
var result = res1.Union(res2).ToList();// Your result is here

enter image description here