-3

Sorry to open another post.

.SelectMany with C#

I asked in the previous post but I can't get the solution for my problem.

`

var departments = stops 
    .Where(stop => stop.InitDate != null)
    .SelectMany(stop => new[] { Month = stop.InitDate.Month, Year = stop.InitDate.Year, Duration = stop.Duration })
    .GroupBy(dt => new { dt.Month, dt.Year }) 
    .OrderBy(g => g.Key.Month)
    .ThenBy(g => g.Key.Year) 
    .Select(g => new 
    { 
        Key = g.Key.Month, 
        Año = g.Key.Year, 
        Duration = g.Sum(v => v.Duration), 
        Count = g.Count() 
    });

`

This is de final solution to my problem, but, when I use this in my code, I have some problems.

If I don't declare the variables "Month, Year, Duration", I get an error in: .SelectMany(stop => new[] { Month = stop.InitDate.Month, Year = stop.InitDate.Year, Duration = stop.Duration })

But I do not know what kind of data they are month and year because if I declare it how integer, I get an error in .GroupBy(dt => new { dt.Month, dt.Year }), because the compiler recognizes dt as integer.

I tried to declare Month and Year as integer and put in the .GroupBy this: .GroupBy(dt => new { Month, Year }) but it is not correct...

Thank you in advance

Raúl

  • 4
    use `new` instead of `new[]` – User.Anonymous Jun 15 '17 at 08:55
  • 3
    You don't need `SelectMany` here. It is used to flatten sequences into one sequence. You don't have any sequences in your stop object. Also sorting by month on first place looks strange – Sergey Berezovskiy Jun 15 '17 at 08:56
  • 2
    Possible duplicate of [.SelectMany with C#](https://stackoverflow.com/questions/43112943/selectmany-with-c-sharp)....Dont ask duplicate questions especially when the first one already has answers – EpicKip Jun 15 '17 at 09:06
  • I think that I need SelectMany because I want order by year and after by month... I need to group all durations for each month-year couple – Raúl Berros Jun 15 '17 at 09:14
  • 1
    @RaúlBerros, as EpicKip said, don't post the same question more times, it's not how SO is supposed to work. If you don't receive satisfying answers, post a bounty on your question to attract more users. – Massimiliano Kraus Jun 15 '17 at 09:37

1 Answers1

0

Apparently you have a sequence named Stops which is a sequence of stop objects. Each stop object may or may have not an InitDate. If it has an InitDate, this InitDate has at least properties Month, Year and Duration, which are all int.

What you want is from your original Stops, only those stop objects that have an InitDate. From every stop object you select, you want to create a new object, with a Key property which contains the Month and the Year and a Duration property which contains the Duration.

You were almost there. Your problem was that you used SelectMany instead of a simple Select.

Normally you use SelectMany if you have a sequence of sequences that you want to concatenate into one sequence. However your Stops does not have a sequence of sequences. Every stop object should produce one "new object with Year, Month and Duration".

Or in simple words: whenever you have a collection of "thingies" and you want to convert every "thingy" into exactly one "other thingy", you should use Select, not SelectMany:

In your case the Select will be:

var stopData = stops 
   .Where(stop => stop.InitDate != null)
   .Select(stop => new
   { 
       GroupKey = new 
       {
           Month = stop.InitDate.Month,
           Year = stop.InitDate.Year,
       },
       Duration = stop.Duration
   });

I put the Year and the Month alreay in a property GroupKey, because that makes the grouping easier:

var groupsOfSameMonth = stopData
    .GroupBy( item => item.Key, item => item.Duration);

Now every group, contains a key, which is the {Month, Year}. The elements of the group are all Durations with this {month, year}. So now all you have to do is from every group, take all elements from the group and Sum() and Count() them:

var durationsOfSameMonth = groupsOfSameMonth
    .Select(group => new 
    { 
       Month = group.Key.Month, // I assumed your Key was an error
       Año = group.Key.Year, 
       Duration = group.Sum(), 
       Count = group.Count() 
    });

All you have to do is some ordering and you are finished.

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116