Reputation: 2650
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.
Upvotes: 3
Views: 16162
Reputation: 713
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>.
Upvotes: 6
Reputation: 148990
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);
Upvotes: 11