【问题标题】:How to merge two IEnumerables?如何合并两个 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);
  • 你试过什么?通常的方法:选择具有相同属性+属性类型的(匿名)类对象。这意味着:将枚举值转换为整数。
  • 您已标记实体框架:您需要在数据库中执行此操作,还是在内存中可以接受?

标签: c# asp.net entity-framework generics


【解决方案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 中。如果您希望发生相反的情况,只需反转值即可。

      【讨论】:

        猜你喜欢
        • 2011-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-05
        • 1970-01-01
        • 2020-11-18
        • 2015-11-07
        相关资源
        最近更新 更多