2013-02-07 12 views
11

Diciamo che ho seguenti dati:gruppo LINQ da blocchi contigui

Tempo Stato
ore 10:00
11:00 Fuori
12:00 Fuori
13:00 Fuori
14 : 00 fuori
ore 15:00
ore 16:00

Come potrei gruppo che l'utilizzo di Linq in qualcosa di simile

[On, [10:00]], [Off, [11:00, 12:00, 13:00, 14:00]], [On, [15:00, 16:00]]

+1

Penso che questo sia un possibile duplicato: http: // StackOverflow.it/questions/7469828/linq-query-to-split-an-ordered-list-in-sublists-of-contiguous-points-by-some-c – hcb

+0

È la domanda, dati i seguenti dati che posso determinare se il l'entità è inserita/disinserita in un dato momento? –

risposta

13

Creare un'estensione GroupAdjacent, come quello indicato here.

e poi è così semplice come:

var groups = myData.GroupAdjacent(data => data.OnOffStatus); 
1

Può essere fatto come.

  1. Iterate sopra la raccolta.
  2. Utilizzare la condizione TakeWhile<Predicate> per attivare o disattivare il primo elemento della raccolta.
  3. Iterate sul sottoinsieme del punto uno e ripetete il passo precedente e concatenate la stringa.

Speranza che aiuta ..

1

Si potrebbe analizzare l'elenco e assegnare un tasto contigua ad esempio, definire una classe:

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

Si potrebbe assegnare valori alla chiave contigua dal scorrendo, mantenendo un conteggio e rilevando quando lo stato cambia da On a Off e così via che ti darebbe una lista come questa:

List<TimeStatus> timeStatuses = new List<TimeStatus> 
      { 
       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"} 
      }; 

quindi utilizzando la seguente query è possibile estrarre lo stato e raggruppati tempi:

var query = timeStatuses.GroupBy(t => t.ContiguousKey) 
    .Select(g => new { Status = g.First().Status, Times = g }); 
3

Ecco un Hardcore soluzione LINQ utilizzando Enumerable.Zip per confrontare elementi contigui e generare una chiave contigue:

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)); 
+0

grazie a dio, sapevo cosa fosse senza cercare effettivamente di analizzarlo –

5

Puoi anche farlo con una query di Linq usando una variabile per tenere traccia delle modifiche, come questa.

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

Fondamentalmente si assegna una chiave per ciascun elemento che incrementa quando l'elemento corrente non è uguale al punto precedente. Naturalmente questo presuppone che i tuoi dati siano in una lista o in una matrice, altrimenti dovresti provare un altro metodo