联合两个对象列表,但根据不同的值删除重复项
Union two lists of object but remove duplicates based on different values
我有两个对象列表:
List1 = [ {id: 1, parentId: null}, {id:2, parentId: null} ]
List2 = [ {id: 3, parentId: 1} ]
我想要 return 这两个的联合列表,但没有 List2 中 List1 的那些,其 id 为 parentId。我在上面的例子中的结果是:
UnionList = [ {id:3, parentId: 1}, {id:2, parentId: null} ]
额外的一件事:两个列表最初是两个 IQueryable;我简单地做了一个 ToList() 将它们作为列表。
如何使用列表(如果不需要 ToList() 则使用 Iqueryables)获得正确的结果?
提前致谢!
我想我得到了你想要的 - 你不想让任何 ID 出现两次。因此,如果在字段 "parent" 中使用了一些 "parent",您不希望它在结果中有额外的作用吗?
在这种情况下,您可以这样做:
var result = List1.Where(x => !List2.Any(l2 => l2.parentId == x.id)).Union(List2);//.ToList();
Where 部分排除了在 List2 中用作父项的所有项目。并且,通过 Union(不包括重复项),它合并了 List2。
ToList() 可能是可选的,具体取决于您接下来要用它做什么。
编辑:从 Concat 更改为 Union。
您可以尝试在遍历 List1 的同时从 List2 中找到第一个匹配的 ParentId
,并根据是否找到添加:
var UnionList = new List<Item>();
foreach (var item in List1)
{
var match = List2.FirstOrDefault(x => x.ParentId == item.Id);
resultList.Add(match ?? item);
}
或仅使用 LINQ:
var UnionList = new List<Item>(List1.Select(item => List2.FirstOrDefault(x => x.ParentId == item.Id) ?? item));
您可以使用 System.Linq
扩展方法 Union
(获得两个列表的并集)以及 Where
和 All
来过滤掉您不需要的项目不想从第一个列表中包含:
var result = list2.Union(list1.Where(l1 => list2.All(l2 => l2.ParentId != l1.Id)));
但是请注意,Union
会使用class的Equals
方法来判断两个项目是否匹配(默认是参考比较),所以你需要覆盖 Equals
和 GetHashCode
以删除重复项(重复项将由您定义,在这种情况下,我想将在两个项目的 Id
属性匹配的位置定义,但是也许你也会包括 ParentId
)。
例如:
public class Item
{
public int Id { get; set; }
public int? ParentId { get; set; }
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
return Id == (obj as Item)?.Id;
}
}
然后一个示例用法是:
public class Program
{
private static void Main(string[] args)
{
var list1 = new List<Item>
{
new Item {Id = 1, ParentId = null},
new Item {Id = 2, ParentId = null},
new Item {Id = 3, ParentId = 1}
};
var list2 = new List<Item>
{
new Item {Id = 3, ParentId = 1}
};
var result = list2.Union(list1.Where(l1 => list2.All(l2 => l2.ParentId != l1.Id)));
GetKeyFromUser("\nDone! Press any key to exit...");
}
}
我有两个对象列表:
List1 = [ {id: 1, parentId: null}, {id:2, parentId: null} ]
List2 = [ {id: 3, parentId: 1} ]
我想要 return 这两个的联合列表,但没有 List2 中 List1 的那些,其 id 为 parentId。我在上面的例子中的结果是:
UnionList = [ {id:3, parentId: 1}, {id:2, parentId: null} ]
额外的一件事:两个列表最初是两个 IQueryable;我简单地做了一个 ToList() 将它们作为列表。
如何使用列表(如果不需要 ToList() 则使用 Iqueryables)获得正确的结果?
提前致谢!
我想我得到了你想要的 - 你不想让任何 ID 出现两次。因此,如果在字段 "parent" 中使用了一些 "parent",您不希望它在结果中有额外的作用吗?
在这种情况下,您可以这样做:
var result = List1.Where(x => !List2.Any(l2 => l2.parentId == x.id)).Union(List2);//.ToList();
Where 部分排除了在 List2 中用作父项的所有项目。并且,通过 Union(不包括重复项),它合并了 List2。 ToList() 可能是可选的,具体取决于您接下来要用它做什么。
编辑:从 Concat 更改为 Union。
您可以尝试在遍历 List1 的同时从 List2 中找到第一个匹配的 ParentId
,并根据是否找到添加:
var UnionList = new List<Item>();
foreach (var item in List1)
{
var match = List2.FirstOrDefault(x => x.ParentId == item.Id);
resultList.Add(match ?? item);
}
或仅使用 LINQ:
var UnionList = new List<Item>(List1.Select(item => List2.FirstOrDefault(x => x.ParentId == item.Id) ?? item));
您可以使用 System.Linq
扩展方法 Union
(获得两个列表的并集)以及 Where
和 All
来过滤掉您不需要的项目不想从第一个列表中包含:
var result = list2.Union(list1.Where(l1 => list2.All(l2 => l2.ParentId != l1.Id)));
但是请注意,Union
会使用class的Equals
方法来判断两个项目是否匹配(默认是参考比较),所以你需要覆盖 Equals
和 GetHashCode
以删除重复项(重复项将由您定义,在这种情况下,我想将在两个项目的 Id
属性匹配的位置定义,但是也许你也会包括 ParentId
)。
例如:
public class Item
{
public int Id { get; set; }
public int? ParentId { get; set; }
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
return Id == (obj as Item)?.Id;
}
}
然后一个示例用法是:
public class Program
{
private static void Main(string[] args)
{
var list1 = new List<Item>
{
new Item {Id = 1, ParentId = null},
new Item {Id = 2, ParentId = null},
new Item {Id = 3, ParentId = 1}
};
var list2 = new List<Item>
{
new Item {Id = 3, ParentId = 1}
};
var result = list2.Union(list1.Where(l1 => list2.All(l2 => l2.ParentId != l1.Id)));
GetKeyFromUser("\nDone! Press any key to exit...");
}
}