группа linq смежными блоками

Предположим, у меня есть следующие данные:

Статус времени
  10:00 На сайте   11:00 Off
  12:00 Off
  13:00 Off
  14:00 Off
  15:00 На сайте   16:00 Вкл.

Как я могу группировать это, используя Linq, в нечто вроде

[Вкл., [10:00]], [Выкл., [11:00, 12:00, 13:00, 14:00]], [Вкл., [15:00, 16:00]]

11
Возникает вопрос, учитывая следующие данные, кто может определить, включен ли объект в данный момент?
добавлено автор Richard Schneider, источник
Я думаю, что это возможный дубликат: stackoverflow.com/questions/7469828/…
добавлено автор hcb, источник

5 ответы

Создайте расширение GroupAdjacent , например, указанное здесь .

И тогда это так просто:

var groups = myData.GroupAdjacent(data => data.OnOffStatus);
11
добавлено

Вы также можете сделать это с помощью одного запроса Linq, используя переменную, чтобы отслеживать изменения, например.

int key = 0;
var query = data.Select(
    (n,i) => i == 0 ? 
        new { Value = n, Key = key } : 
        new 
        { 
            Value = n, 
            Key = n.OnOffFlag == data[i - 1].OnOffFlag ? key : ++key 
        })
    .GroupBy(a => a.Key, a => a.Value);

В основном он назначает ключ для каждого элемента, который увеличивается, когда текущий элемент не равен предыдущему элементу. Конечно, это предполагает, что ваши данные находятся в списке или массиве, иначе вам придется попробовать другой метод

5
добавлено

Ниже приведено решение hardcore LINQ с помощью Enumerable.Zip для сравнения смежных элементов и создания непрерывного ключа:

var adj = 0;
var t = data.Zip(data.Skip(1).Concat(new TimeStatus[] { null }),
        (x, y) => new { x, key = (x == null || y == null || x.Status == y.Status) ? adj : adj++ }
    ).GroupBy(i => i.key, (k, g) => g.Select(e => e.x));
3
добавлено
Слава богу, я знал, что это было без фактического попытки разобрать это
добавлено автор nik.shornikov, источник

Это можно сделать как.

  1. Iterate over collection.
  2. Use TakeWhile condition is text of first element of collection On or Off.
  3. Iterate over the subset of from point one and repeat above step and concatenate string.

Надеюсь, поможет..

1
добавлено

Вы можете разобрать список и назначить смежный ключ, например, определить класс:

public class TimeStatus
{
    public int ContiguousKey { get; set; }
    public string Time { get; set; }
    public string Status { get; set; }
}

Вы присваиваете значения непрерывному ключу путем циклического перехода, поддерживая подсчет и определяя, когда статус меняется с «Вкл.» На «Выкл.» И т. Д., Что даст вам список:

List timeStatuses = new List 
            {
                new TimeStatus { ContiguousKey = 1, Status = "On", Time = "10:00"},
                new TimeStatus { ContiguousKey = 1, Status = "On", Time = "11:00"},
                new TimeStatus { ContiguousKey = 2, Status = "Off", Time = "12:00"},
                new TimeStatus { ContiguousKey = 2, Status = "Off", Time = "13:00"},
                new TimeStatus { ContiguousKey = 2, Status = "Off", Time = "14:00"},
                new TimeStatus { ContiguousKey = 3, Status = "On", Time = "15:00"},
                new TimeStatus { ContiguousKey = 3, Status = "On", Time = "16:00"}
            };

Затем, используя следующий запрос, вы можете извлечь статус и сгруппировать Times:

    var query = timeStatuses.GroupBy(t => t.ContiguousKey)
    .Select(g => new { Status = g.First().Status, Times = g });
1
добавлено
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot