C# LINQ合并2个列表,保留sequence和origin
这里有两个相同对象类型的列表C# LINQ合并2个列表,保留sequence和origin,c#,list,linq,merge,C#,List,Linq,Merge,这里有两个相同对象类型的列表 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
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来做这个,但还是被卡住了
请告知
谢谢 试试这样的方法:
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();
下面是一些使用Linq实现所需功能的代码。它基本上遍历所有旧列表,并通过从新列表中查找匹配项并在未找到匹配项的情况下添加null作为第二项,将对添加到合并列表中。然后,它遍历新列表中的其余项,并在第一个项中添加null。它选择一个具有两个属性的动态类型:OldSet和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"},
};
输出
你可以左键连接两个列表。我编辑了答案,因为您实际上需要左联合两次,并应用select distinct以获得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();
可能有点过分,但是如果你真的想用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();
在这种情况下,您必须使用两个GroupJoin和Union来计算结果。 请看以下代码:
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
听说过字典吗?还是多维数组?合并集的类型是什么?是列表吗?我认为结果类型可以是可选的。只要我能分辨出这个项目是从旧集或新闻集,并结合那些具有相同的id。感谢peeps的提示如果你能提供一个新的。您的代码未按原样编译。您的问题中缺少以下详细信息以提供有用的答案:1旧集和新集的项目顺序是否相同,即如果同一索引中的项目id不匹配,是否可以安全地假定其他列表中不存在该项目?2应该维护谁的顺序?也就是说,如果两个列表中的所有内容都是不同的,并且没有任何项目的单一匹配,那么输出应该是什么?问题有点不明确,但他似乎不只是压缩它们,而是根据数据中的数字进行配对。这对于这项任务来说,代码太多了。。。。Linq的存在就是为了做这种事情。在这里使用元组没有任何意义,几个连接或联合就可以了。你是对的,我更正了代码,删除了不相关的注释…:@醉鬼很酷。我还修改了我的代码,将合并代码从两行减少到一行,并使用了动态类型,以防有人投了反对票。
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