Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ合并2个列表,保留sequence和origin_C#_List_Linq_Merge - Fatal编程技术网

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