2

Here is a simplified version of my class structure:

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; }
}

What I want to do is take all the Data objects in the eventData lists and put them in a new grouped list of lists that's grouped by date.

I thought about putting all the Data objects into a temporary list and then grouping that list with Linq but I'd like to know if there's a more elegant way to do it without using a temporary list.

David DeMar
  • 2,390
  • 2
  • 32
  • 45

3 Answers3

10

If I understand what you want, something like this should work:

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

Or in fluent syntax:

var results = transferObject.events
    .SelectMany(e => e.eventData)
    .GroupBy(d => d.date);
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
5

Well, it depends on the data you're looking for. If you don't care about the actual Date values, just that the integers are grouped by them (and I suspect also sorted by them), from a reference to the Event class you would have:

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

However, if you care about the dates, there are two ways you could possibly go. You can end up discarding any references to the Data class:

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());

Or you can keep the Data objects:

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

But supposing you wanted to do this from a reference to the TransferObject class. Then, you would do pretty much the same thing, but would need to use the SelectMany function:

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();

The key here is that the SelectMany function essentially concatenates one level of collections that a normal Select would return, i.e.

any IEnumerable<IEnumerable<T>> becomes an IEnumerable<T>.
moron4hire
  • 703
  • 5
  • 13
  • I'm not sure if the first three will work because `date` is not a property of `eventData`. – David DeMar Aug 27 '13 at 17:22
  • In the first three examples, the evt variable is of type Event. Your original question asked how to query the eventData list, which contains Data objects. I added the last three examples just in case you actually meant to ask how to query a TransferObject object to get to the retrieve and group the Data objects once removed. – moron4hire Aug 27 '13 at 18:28
-2

I would do something slightly different I would would send them to your own list:

var results;

private method(Date date)
{

     resuts = evt.eventData.Where(a=> a.Date == date).toList();

}
Malcor
  • 2,667
  • 21
  • 29