【问题标题】:How to group a list of lists by date using Linq?如何使用 Linq 按日期对列表进行分组?
【发布时间】:2013-08-28 06:40:22
【问题描述】:

这是我的类结构的简化版本:

public class TransferObject
{
    public List<Event> events { get; set; }

    public TransferObject()
    {
        events = new List<Event>();
    }
}

public class Event
{
    public List<Data> eventData { get; set; }

    public Event()
    {
        eventData = new List<Data>();
    }
}

public class Data
{
    public int someData {get; set;}
    public DateTime date { get; set; }
}

我想要做的是获取eventData 列表中的所有Data 对象,并将它们放入由date 分组的新列表分组列表中。

我曾考虑将所有 Data 对象放入一个临时列表中,然后使用 Linq 将该列表分组,但我想知道是否有更优雅的方法可以在不使用临时列表的情况下做到这一点。

【问题讨论】:

  • 你有什么输入?
  • eventData.OrderBy(x =&gt; x.date); 应该可以工作(未经测试)
  • 这样的? var evtByDate = evt.eventData.GroupBy(x =&gt; x.Date).ToDictionary(x =&gt; x.Key, x =&gt; x.ToList());

标签: c# linq


【解决方案1】:

如果我明白你想要什么,这样的事情应该可以工作:

var results = 
    from e in transferObject.events
    from d in e.eventData
    group d by d.date;

或者用流利的语法:

var results = transferObject.events
    .SelectMany(e => e.eventData)
    .GroupBy(d => d.date);

【讨论】:

    【解决方案2】:

    嗯,这取决于您要查找的数据。如果您不关心实际的 Date 值,只需将整数按它们分组(我怀疑也按它们排序),来自对 Event 类的引用,您将拥有:

    List<List<int>> byDate = evt.eventData
        .GroupBy(d => d.date)
        .OrderBy(g=>g.Key)
        .Select(g => g.Select(v => v.someData)
            .ToList())
        .ToList();
    

    但是,如果您关心日期,则可以采用两种方法。您最终可以丢弃对 Data 类的任何引用:

    Dictionary<DateTime, List<int>> byDate2 = evt.eventData
        .GroupBy(d => d.date)
        .OrderBy(g=>g.Key)
        .ToDictionary(
            g=>g.Key, 
            g => g.Select(v => v.someData)
                .ToList());
    

    或者您可以保留 Data 对象:

    List<List<Data>> byDate = evt.eventData
        .GroupBy(d => d.date)
        .OrderBy(g => g.Key)
        .Select(g => g.ToList())
        .ToList();
    

    但是假设您想通过对 TransferObject 类的引用来执行此操作。然后,您将执行几乎相同的操作,但需要使用 SelectMany 函数:

    TransferObject txobj = new TransferObject(); // however this happens
    List<List<int>> byDate = txobj.events
        .SelectMany(evt=>evt.eventData
            .GroupBy(d => d.date)
            .OrderBy(g => g.Key)
            .Select(g => g.Select(v => v.someData)
                .ToList()))
        .ToList();
    
    Dictionary<DateTime, List<int>> byDate2 = txobj.events
        .SelectMany(e=>e.eventData)
        .GroupBy(d => d.date)
        .OrderBy(g=>g.Key)
        .ToDictionary(
            g=>g.Key, 
            g => g.Select(v => v.someData)
                .ToList());
    
    List<List<Data>> byDate3 = txobj.events
        .SelectMany(evt=>evt.eventData
            .GroupBy(d => d.date)
            .OrderBy(g => g.Key)
            .Select(g => g.ToList()))
        .ToList();
    

    这里的关键是 SelectMany 函数本质上连接了普通 Select 将返回的一级集合,即

    any IEnumerable<IEnumerable<T>> becomes an IEnumerable<T>.
    

    【讨论】:

    • 我不确定前三个是否有效,因为date 不是eventData 的属性。
    • 在前三个示例中,evt 变量的类型为 Event。您最初的问题询问如何查询包含 Data 对象的 eventData 列表。我添加了最后三个示例,以防您实际上是想询问如何查询 TransferObject 对象以获取检索并在删除后对 Data 对象进行分组。
    【解决方案3】:

    我会做一些稍微不同的事情,我会将它们发送到您自己的列表中:

    var results;
    
    private method(Date date)
    {
    
         resuts = evt.eventData.Where(a=> a.Date == date).toList();
    
    }
    

    【讨论】:

    • 我不明白这是如何解决这个问题的。它甚至没有编译。
    猜你喜欢
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 2016-09-09
    • 2016-02-21
    相关资源
    最近更新 更多