【问题标题】:How to change values of few properties from one list to another using LINQ C#:如何使用 LINQ C# 将几个属性的值从一个列表更改为另一个列表:
【发布时间】:2019-01-08 09:51:24
【问题描述】:

我有两个类似的列表

List<Customer> customer = new List<Customer>() 
 { Id =1 , Name = 'Demo1' , OrderId = 123}
 { Id =1 , Name = 'Demo2' , OrderId = 123}

List<Order> order = new List<Order>() 
{ Id =77 , CustomerName = 'Demo1'}
{ Id =88 , CustomerName = 'Demo2'}

我要替换customer.OrderId = order.Id where order.CustomerName = customer.Name

我要替换customer list OrderId value from order list when CustomerName is matching with Name prop

我正在尝试这样的事情 -

customer = order.Select(eo => new Customer { Name = eo.CustomerName });

这是不正确的 LINQ 有人可以在这里纠正我吗?

【问题讨论】:

    标签: c# linq c#-4.0


    【解决方案1】:

    LINQ 主要适用于查询,而不是数据修改。

    相反,我会使用简单的foreach

    foreach (var c in customer)
    {
        var o = order.FirstOrDefault(o => o.CustomerName == c.Name);
        c.OrderId = o?.Id ?? 0;
    }
    

    当然,当每个客户有多个订单时,这种方法也不会奏效。另外我建议将变量重命名为复数 - customersorders 以更好地表示它们的含义。

    对于纯粹的 LINQ 方法,您可以编写 ForEach LINQ 扩展方法,但我发现明确的 foreach 是一种更易读的解决方案。

    【讨论】:

      【解决方案2】:

      LINQ 主要用于查询。您可以创建一个符合您要求的新列表。

      如果需要,您可以将此新列表分配给您的可变客户。

      您想加入您的客户并以客户的名义下订单。

      简单的解决方案:

      var joinResult = customers.Join(orders,    // join the tables of customers with orders
          customer => customer.Name,             // from every customer take the Name
          order => order.CustomerName,           // from every order take the CustomerName
          (customer, order) => new Customer      // when they match make a new Customer
          {
              Id = customer.Id,                  // take Id and Name from the matching Customer
              Name = customer.Name,
              OrderId = order.Id,                // take the OrderId from the matching order
          })
          .ToList();
      customers = joinResult;
      

      唉,如果你有一个 Customer 和几个 Orders,这将不起作用:

      var customers = new List<Customer>() 
          { Id = 1 , Name = 'John Doe' , OrderId = 123},
      
      var orders = new List<Order>() 
          { Id =77 , CustomerName = 'John Doe'}
          { Id =88 , CustomerName = 'John Doe'}
      

      客户 1 的 OrderId 应该是 77 还是 78?

      您确定每个客户只有一个订单吗?

      要获得Customer with all his Orders,请使用GroupJoin

      var result = customers.GroupJoin(orders, // GroupJoin the customers with orders
          customer => customer.Name,           // from every customer take the Name
          order => order.CustomerName,         // from every order take the CustomerName
          (customer, orders) => new            // for every customer with all his matching orders
          {                                    // make one new object
              Id = customer.Id,                  // take Id and Name from the matching Customer
              Name = customer.Name,
      
              // TODO Decide what to do if there are several orders for customer with this name
              // Keep all orders? Or keep the oldest one, the newest one?
              // the unpaid ones?
              AllOrders = orders.ToList(),
              OldestOrder = orders.Orderby(order => order.Date).FirstOrDefault(),
              NewestOrder = orders.OrderByDescending(order => order.Date).FirstOrDefault(),
              UnpaidOrders = orders.Where(order => order.Status == Status.Unpaid).ToList(),
          })
          .ToList();
      

      【讨论】:

        【解决方案3】:

        您想要执行 join 操作(很可能是内部连接)。 LINQ 提供了这样的功能

        var customerOrders = customer.Join(order,
            c => c.Name,
            o => o.CustomerName,
            (customer, order) =>
            {
                custumer.OrderId= order.Id;
                return customer;
            }).ToList();
        

        但正如@Martin Zikmund 所说,我会小心直接处理数据。

        【讨论】:

          【解决方案4】:

          您需要将来自客户的属性Name 和来自订单的属性CustomerName 加入两个列表,然后从类似订单中分配OrderId

          List<Customer> result = new List<Customer>();
          
          result = (from c in customer
                    join o in order on c.Name equals o.CustomerName
                    select new Customer
                    {
                        Id = c.Id,
                        Name = c.Name,
                        OrderId = o.Id
                    }).ToList();
          
          foreach (var item in result)
          {
              Console.WriteLine($"Id: {item.Id}, \t Name: {item.Name}, \t OrderId: {item.OrderId}");
          }
          
          Console.ReadLine();
          

          输出:

          【讨论】:

            【解决方案5】:

            您可以遍历客户订单和代理订单对,并仅更新匹配对的客户。

            var matched = customers.Join(orders,
                                         customer => customer.Name,
                                         order => order.CustomerName,
                                         (customer, order) => (Customer: customer, Order: order));
            
            foreach (var pair in matched)
            {
                pair.Customer.OrderId = pair.Order.Id;
            }
            

            请注意,如果订单集合包含多个具有相同客户名称的订单,Join 方法将使用集合中最后出现的订单 ID 更新客户。

            以“函数式”方式设计的 LINQ 扩展方法,其中枚举项作为不可变处理。 LINQ 方法总是返回集合的新实例。如果项目在枚举方法期间发生变异,大多数开发人员会“非常”惊讶。
            因此,明确的foreach 循环将清楚地告诉其他开发人员您的意图。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-08-22
              • 1970-01-01
              • 2021-10-16
              • 1970-01-01
              • 2011-10-13
              • 1970-01-01
              相关资源
              最近更新 更多