如何使用LINQ C#将一些属性的值从一个列表更改为另一个列表:

问题描述 投票:0回答:5

我有两个列表

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
5个回答
4
投票

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;

唉,如果你有几个CustomerOrders,这将不起作用:

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是否应该订购订单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();

1
投票

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

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

但正如@Martin Zikmund所说,我要小心直接操纵数据。


1
投票

您需要从客户和物业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();

输出:

enter image description here


1
投票

您可以循环访问客户和代理订单对,并仅为匹配对更新客户。

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循环将清楚地告诉其他开发人员你的意图。

© www.soinside.com 2019 - 2024. All rights reserved.