如何合并两个 IEnumerables?
Posted
技术标签:
【中文标题】如何合并两个 IEnumerables?【英文标题】:How to merge two IEnumerables? 【发布时间】:2022-01-07 05:41:30 【问题描述】:我有两个 Enumberable 列表:list1 和 list2 我想从 list2 中获取一些东西并根据条件在 list1 中更新它
例如:list1.Id 表示例如 1、2、3、4、5 等。 list2.Id 有 3, 4 我需要比较这些 Id 并从 list2 中获取与 list1.Id 匹配的其他字段(例如名称、主题)(在本例中为 3 和 4)并将其复制到 list1 其他字段(名称、主题)
列表1:
Id | Name | Subject |
---|---|---|
1 | N1 | S1 |
2 | N2 | S2 |
3 | ||
4 | ||
5 | N5 | S5 |
列表2:
Id | Name | Subject |
---|---|---|
3 | N3 | S3 |
4 | N4 | S4 |
所需结果:
Id | Name | Subject |
---|---|---|
1 | N1 | S1 |
2 | N2 | S2 |
3 | N3 | S3 |
4 | N4 | S4 |
5 | N5 | S5 |
【问题讨论】:
枚举是在编译过程中创建的,在执行过程中不能修改,或者我误解了一些东西 @Frenchy 他们在谈论可枚举序列,而不是enum
定义
类似var result = enum1.Where(item => !string.IsNullOrEmpty(item)).Union(enum2);
你试过什么?通常的方法:选择具有相同属性+属性类型的(匿名)类对象。这意味着:将枚举值转换为整数。
您已标记实体框架:您需要在数据库中执行此操作,还是在内存中可以接受?
【参考方案1】:
不太清楚你需要什么。我假设您需要根据 enum2 更新 enum1 中的数据,在这种情况下这样做:
foreach(var item in enum2)
var itemToUpdate = enum1.SingleOrDefault(x => x.Id == item.Id);
if (itemToUpdate == null) continue;
itemToUpdate.Name = item.Name;
itemToUpdate.Subject = item.Subject;
【讨论】:
【参考方案2】:假设您的课程主题如下:
class Suabject
public int id;
public string name;
public string Subject;
你有两个列表如下:
List<Suabject> enum1 = new List<Suabject>();
List<Suabject> enum2 = new List<Suabject>();
如果你想合并它们,你所做的基本上是遍历 enum2 中的所有项目并检查项目是否存在于 enum1 中然后你更新它。如果没有,您可以将其添加到列表中。如下:
foreach (var item in enum2)
var s = enum1.FirstOrDefault(x=> x.id == item.id);
if(s != null)
s.name = item.name;
s.Subject = item.Subject;
else
enum1.Add(s);
这样,enum1 将是两者的合并列表。
【讨论】:
感谢您的回复。所有三个答案都解决了目的,但可以在没有 foreach 的情况下完成吗? @RaghavendraHG 请注意,使用FirstOrDefault(...)
的答案具有 O(n^2) 复杂性,并且随着您使两个列表变大而扩展性会更差(尽管对于小数字并不重要元素)
@canton7 你会推荐什么?
任何使用恒定时间查找来查找给定 ID 的匹配项的东西。 Oliver 的回答是使用 GroupBy 来完成的,但您也可以使用 Dictionary【参考方案3】:
this怎么样?
var listOne = new[]
new Entity Id = 1, Name = "N1", Subject = "S1" ,
new Entity Id = 2, Name = "N2", Subject = "S2" ,
new Entity Id = 3 ,
new Entity Id = 4 ,
new Entity Id = 5, Name = "N5", Subject = "S5" ,
;
var listTwo = new[]
new Entity Id = 3, Name = "N3", Subject = "S3" ,
new Entity Id = 4, Name = "N4", Subject = "S4" ,
;
// Join to lists by using 1:1 relationship
var pairs = listOne.Join(listTwo, entity => entity.Id, entity => entity.Id, (one, two) => (one, two));
foreach (var pair in pairs)
// Update first name, if empty
if(string.IsNullOrEmpty(pair.one.Name))
pair.one.Name = pair.two.Name;
// Update first subject, if empty
if(string.IsNullOrEmpty(pair.one.Subject))
pair.one.Subject = pair.two.Subject;
// Save and show elements
foreach (var item in listOne)
Console.WriteLine(JsonConvert.SerializeObject(item));
【讨论】:
【参考方案4】:如果您正在寻找没有 Foreach 的解决方案,您是否想过在这部分使用字典,将键设置为对象的 id,将值设置为对象本身。
Dictionary<int, ObjectType> dictA = new Dictionary<int, ObjectType>();
你在哪里添加这样的值:
dictA.Add(object.Id, object);
然后你就可以像这样在没有 Foreach 的情况下进行合并:
dictA = dictA.Concat(dictB.Where(b => !dictA.ContainsKey(b.Key))).ToDictionary(b => b.Key, b => b.Value);
这样,dictB 被合并到 dictA 中。如果您希望发生相反的情况,只需反转值即可。
【讨论】:
以上是关于如何合并两个 IEnumerables?的主要内容,如果未能解决你的问题,请参考以下文章
C#中的IEnumable与IEnumator接口的简单理解
按值比较迭代类型(IEnumerables及其亲属)(以检查相等性)
InvalidCastException:无法将“System.Collections.Generic.List”类型的对象转换为 System.Collections.Generic.IEnumer