【问题标题】:.Net List ForEach Item.Net 列出每个项目
【发布时间】:2012-12-07 00:08:41
【问题描述】:

我有 2 个对象:

public class ClassA
{
   public int Id
   public string name;

   public ClassB myObjectB;

}
public class ClassB
{
   public int Id
   public string name
}

有 2 个列表 List1 中的某些项目按 Id 与 List2 上的项目匹配...我想为每个项目设置 objectB...

foreach(ClassA item in List1)
{
   ClassB obj = (from b in List2 where b.Id == item.Id select b).SingleOrDefault()
   if(obj != null)
   {
       item.myObjectB = obj; 
       ////////break;    <- ignore this
   }
}

这个解决方案对我有用,但我只是想知道是否有更好的方法来代替 Foreach

感谢大家的帮助!!!

【问题讨论】:

  • 您可能应该删除 break; 以使其适用于 List1 的每个项目
  • 那是非常糟糕的代码。你可以用选择完成List2.SingleOrDefault(x=&gt;x.Id == item.Id); 而不是所有的查询语法废话。

标签: c# .net linq list foreach


【解决方案1】:

我认为foreach,在这种情况下,实际上是合适的方法,因为你正在改变你的列表。但是,您可能会稍微简化代码:

foreach(ClassA item in List1)
{
    item.myObjectB = List2.FirstOrDefault(b => b.Id == item.Id);
}

这将每次设置项目,但如果没有匹配项,它将设置为null。如果您在 myObjectB 中已经有项目并且将它们设置为 null 是不合适的,您可以使用:

foreach(ClassA item in List1)
{
    item.myObjectB = List2.FirstOrDefault(b => b.Id == item.Id) ?? item.myObjectB;
}

【讨论】:

  • 看起来 OP 在第一场比赛之后就被打破了,所以也许他不需要foreach
  • 哦,当我写我的代码的简化版本时,我把 break 放在那里,但是很好,break 不应该在那里......
【解决方案2】:

扩展 Reed 的答案。您实际上可以单行执行此操作,因为列表具有 ForEach 方法。

List1.ForEach(item => item.myObjectB = List2.FirstOrDefault(b => b.Id == item.Id) ?? item.myObjectB);

【讨论】:

    【解决方案3】:
    List<ClassA> list1 = new List<ClassA>();
    List<ClassB> list2 = new List<ClassB>();
    
    list1.Add(new ClassA { Id = 2, name = "a2" });
    list1.Add(new ClassA { Id = 3, name = "a3" });
    list1.Add(new ClassA { Id = 4, name = "a4" });
    list1.Add(new ClassA { Id = 5, name = "a5" });
    
    list2.Add(new ClassB { Id = 1, name = "b1" });
    list2.Add(new ClassB { Id = 2, name = "b2" });
    list2.Add(new ClassB { Id = 4, name = "b4" });
    list2.Add(new ClassB { Id = 5, name = "b5" });
    
    // Goal is to set ClassA::myObjectB from List1 to 
    // matching instance (if any) of ClassB from List2
    var query = 
        from a in list1
        from b in list2
        where a.Id == b.Id
        select Tuple.Create(a, b);  
    foreach (var element in query)
        element.Item1.myObjectB = element.Item2;
    

    更新

    或者,如果你真的不想要一个 for 循环,我刚刚意识到你可以利用赋值返回一个值的事实,同时在混淆代码竞赛中输入:)

    (from a in list1
     from b in list2
     where a.Id == b.Id
     select a.myObjectB = b).ToList();
    

    更新2

    我只是想到了另一种方法 - 根据您的情况,惰性机制可能适合您?

    public class ClassA
    {
       public int Id
       public string name;
    
       private ClassB myObjectB;
       public ClassB MyObjectB { 
          get { return myObjectB ?? (myObjectB = list2.FirstOrDefault(x => this.Id == x.Id)); } 
       }
    }
    

    【讨论】:

    • 请记住,您可以在 linq 中使用匿名类型,并且比使用 turple 更清晰。
    • 我个人觉得这值得商榷,因为在这种情况下,匿名类型的成员名称最终会包含冗余信息——但我并没有说你错了,我只是认为我已经对此有所了解。 ..
    【解决方案4】:

    类定义如下:

    class ClassA {
       public int Id { get; private set; }
       public string name { get; private set; }
    
       public ClassB myObjectB { get; set; }
    
       public ClassA(int pId, string pName) {
          Id = pId;
          name = pName;
       }
    }
    
    class ClassB {
       public int Id { get; private set; }
       public string name { get; private set; }
    
       public ClassB(int pId, string pName) {
          Id = pId;
          name = pName;
       }
    }
    

    您可以使用 LINQ Join 方法执行以下操作:

    var listA = new List<ClassA> {
       new ClassA(1, "OneA"),
       new ClassA(2, "TwoA"),
       new ClassA(3, "ThreeA")
    };
    
    var listB = new List<ClassB> {
       new ClassB(1, "OneB"),
       new ClassB(2, "TwoB"),
       new ClassB(4, "FourB")
    };
    
    listA
    .Join(
       listB,
       itemA => itemA.Id,
       itemB => itemB.Id,
       (itemA, itemB) => new { ItemA = itemA, ItemB = itemB }
    ).ForEach(pair => pair.ItemA.myObjectB = pair.ItemB);
    
    listA.ForEach(itemA => Console.WriteLine(
       "{0} maps to {1}",
       itemA == null
          ? "null"
          : itemA.name,
       (itemA == null || itemA.myObjectB == null)
          ? "null"
          : itemA.myObjectB.name
    ));
    

    输出是:

    OneA maps to OneB
    TwoA maps to TwoB
    ThreeA maps to null
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2022-11-07
      • 2018-01-29
      • 2016-10-26
      • 1970-01-01
      相关资源
      最近更新 更多