如何使用LINQ将共享一个属性的两个列表合并为第三个列表

本文关键字:列表 三个 两个 合并 一个 LINQ 何使用 共享 属性 | 更新日期: 2023-09-27 17:50:43

我想创建以下类的列表(list(:

public class StatusData
{
    public DateTime? Date { get; set; }
    public int RegisteredUsers { get; set; }
    public int Orders { get; set; }
    public decimal Import { get; set; }
}

该列表应填充另外两个列表的信息:List<Contact>List<Purchase>。两个类都有以下形状:

public class Contact
{
    public DateTime? RegisterDate { get; set; }
    public string Name { get; set; }
}
public class Purchase
{
    public DateTime? PurchaseDate { get; set; }
    public int PurchaseID {get;set;}
    public int Import { get; set; }
}

这个想法是,列表应该每天显示注册用户的数量、购买量和这些购买的总进口量。所以,从本质上讲,两者只是共享日期。

但是,我无法提供一个好的LINQ表达式来创建List。我考虑的一个解决方案是检索2个列表中所有不同的日期,然后对它们进行迭代以检索我想要的信息,但我认为这种方法相当"丑陋"。有什么方法可以轻松地做我想做的事吗?

编辑:我想要的例子如下:

Contacts
--------
Name      RegisteredDate
David     10/10/2013
Paul      09/10/2013
Gina      10/10/2013
Roger     09/10/2013
Rose      05/10/2013
Jean      07/10/2013
Mark      04/10/2013
Lisa      04/10/2013

Purchases
-----------
ID          PurchaseDate           Import
1           10/10/2013             10
2           10/10/2013             10
3           10/10/2013             20
4           04/10/2013             15
5           04/10/2013             15
6           07/10/2013             20
7           07/10/2013             2
8           07/10/2013             2

Expected result
----------------
Date          RegisteredUsers     Purchases      Import
04/10/2013    2                   2              30
05/10/2013    1                   0              0
07/10/2013    1                   3              24
09/10/2013    2                   0              0
10/10/2013    2                   3              40

亲切问候

如何使用LINQ将共享一个属性的两个列表合并为第三个列表

var contacts = new List<Contact>();
var purchases = new List<Purchase>();
var dates = contacts.Select(x => x.RegisterDate.Value)
                    .Concat(purchases.Select(x => x.PurchaseDate.Value))
                    .Distinct();
var data = from date in dates
           join c in contacts on date equals c.RegisterDate.Value into registered
           join p in purchases on date equals p.PurchaseDate.Value into purchased
           select new StatusData {
               Date = date,
               RegisteredUsers = registered.Count(),
               Orders = purchases.Count(),
               Import = purchases.Sum(x => x.Import)
           };

当至少进行了一次注册一次购买时,它将返回所有天的StatusData

所以这里有几个单独的任务。您要做的第一件事是按注册日期对联系人进行分组。接下来,您将根据日期将结果加入到Purchases表中,聚合两个不同列上的计数/总和。LINQ对这两种操作都有一种方法:

var query = from contact in contacts
    group contact by contact.RegisterDate into contactGroup
    join purchase in purchases
    on contactGroup.Key equals purchase.PurchaseDate into purchaseGroup
    select new StatusData
    {
        Date = contactGroup.Key,
        RegisteredUsers = contactGroup.Count(),
        Orders = purchaseGroup.Count(),
        Import = purchaseGroup.Sum(p => p.Import),
    };

这实际上是两个单独的查询,它们的结果在最后合并。

var contact = from c in Contact
              group c by c.RegisterDate into c
              select new StatusData
              {
                Date = c.Key,
                RegisteredUsers = c.Count(),
                Orders = 0,
                Import = 0,
              };
var purchases = from p in Purchases
                group p by p.PurchaseDate into p
                select new StatusData
                {
                  Date = p.Key,
                  RegisteredUsers = 0,
                  Orders = p.Count(),
                  Import = p.Sum(x => x.Import),
                };
var final = from x in contact.Concat(purchases)
            group x by x.Date into x
            select new StatusData
            {
              Date = x.Key,
              RegisteredUsers = x.Sum(y => y.RegisteredUsers),
              Orders = x.Sum(y => y.Orders),
              Import = x.Sum(y => y.Import),
             };