Grupowanie danych po TimeSpan z interwałem

0

Cześć,
mam problemem z grupowaniem danych i chciałbym Was prosić o pomoc.

Mam:

var groupItems = items.OrderBy(p => p.Godzina).GroupBy(obj => new { obj.Godzina, obj.Zadanie, obj.Osoba }).ToList();

Zależy mi jednak, żeby w przypadku grupowania po "obj.Godzina" (jest typu TimeSpan) brane były elementy również z czasem + 1 minuty.
Załóżmy, że mam już posortowane godziny: 1300, 1300, 1300, 1300, 1300, 1300, 1300.
Chciałbym dostać:

Grupa 1:
13:08:00
13:09:00
13:09:00

Grupa 2:
13:10:00
13:11:00

Grupa 3:
13:12:00
13:13:00

Jakaś wskazówka jak to ugryźć? :)
Pozdrawiam

0

Zamień TimeSpan na DateTime (data w DateTime ciebie nie interesuje) i wtedy możesz zrobić tak

List<DateTime> times = new List<DateTime>() 
{
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 21, 0),
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 1, 0),
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 12, 0),
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 4, 0),
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 55, 0),
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 43, 0),
  new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 22, 0)
};
		
var groupedItems = times.OrderBy(x=>x.Hour).GroupBy(x=>x.Minute);

Nie bardzo rozumiem to grupowanie, bo to musi mieć jakąś logikę 🤔

Biorę pierwszy z listy (13:08) i każdy minuta + 1 wchodzi w skład grupy?

1

a dlaczego 1300 nie wchodzi do grupy z 1300 skoro jest minuta + 1? Gdyby wchodziło to można by było coś wykombinować, ale tak to logika jest na tyle pokrętna że będziesz musiał chyba zrobić zwykłą pętlę i warunki z customowymi grupami, bo prawdopodobnie się nie da prosto wyznaczyć początki tych grup

0

Liczy się to od najniższego. Jeśli 13:08 jest pierwszy to +1 jest 13:09, ten 13:10 jest już +2, więc staje się currentItem i od niego znowu +1 itd 🤔

0
List<TimeSpan> times = new()
{
    new(13, 0, 0),
    new(13, 1, 0),
    new(13, 9, 0),
    new(13, 10, 0),
    new(13, 11, 0),
    new(13, 12, 0),
    new(13, 59, 0),
    new(14, 59, 0),

};

var groupedTimes = times.GroupBy(x => x.Minutes % 2 is 0 ? (x.Hours, x.Minutes) : (x.Hours, x.Minutes - 1));
int counter = 1;

foreach (var group in groupedTimes )
{
    Console.WriteLine($"Grupa: {counter++}");
    
    foreach (TimeSpan time in group)
    {
        Console.WriteLine(time.ToString());
    }

    Console.WriteLine();
}
0
AbcDefGhi napisał(a):
var groupedTimes = times.GroupBy(x => x.Minutes % 2 is 0 ? (x.Hours, x.Minutes) : (x.Hours, x.Minutes - 1));

to da niepoprawne wyniki dla nieparzystych minut, nie mówiąc o tym że nie bierze pod uwagę sekund, moim zdaniem 1359 nie powinna się znaleźć w tej samej grupie co 1301:

Grupa: 1
13:00:00
13:01:00

Grupa: 2
13:09:00

Grupa: 3
13:10:00
13:11:00

Grupa: 4
13:12:00

Grupa: 5
13:59:00

Grupa: 6
14:59:00

według mojej interpretacji wątku powinno być:

Grupa: 1
13:00:00
13:01:00

Grupa: 2
13:09:00
13:10:00

Grupa: 3
13:11:00
13:12:00

Grupa: 4
13:59:00

Grupa: 5
14:59:00

Można to zrobić używając Aggregate i pamiętając gdzie się zaczynała ostatnia grupa:

List<TimeSpan> times = new()
{
    new(13, 0, 0),
    new(13, 1, 0),
    new(13, 9, 0),
    new(13, 10, 0),
    new(13, 11, 0),
    new(13, 12, 0),
    new(13, 59, 0),
    new(14, 59, 0),
};

var groupedTimes = times.Aggregate(
    new List<(TimeSpan start, IList<TimeSpan> items)>(),
    (groups, time) =>
    {
         var lastGroup = groups.LastOrDefault();
         if (time - lastGroup.start > TimeSpan.FromMinutes(1))
         {
             lastGroup = (time, new List<TimeSpan>());
             groups.Add(lastGroup);
         }

         lastGroup.items.Add(time);
         return groups;
     });

int counter = 1;

foreach (var group in groupedTimes)
{
    Console.WriteLine($"Grupa: {counter++}");

    foreach (TimeSpan time in group.items)
    {
        Console.WriteLine(time.ToString());
    }

    Console.WriteLine();
}

Można się pokusić o klasę która zaimplementuje IGrouping<> żeby działało to podobnie do GroupBy

1 użytkowników online, w tym zalogowanych: 0, gości: 1