2016-07-27 13 views
5

Ich möchte eine neue Gruppe erstellen, wenn der Unterschied zwischen den Werten in Zeilen größer als fünf ist.Wie kann ich nach dem Unterschied zwischen Zeilen in einer Spalte mit linq und C# gruppieren?

Beispiel:

int[] list = {5,10,15,40,45,50,70,75}; 

sollte mir 3 Gruppen geben:

1,[ 5,10,15 ] 
2,[40,45,50] 
3,[70,75] 

Ist es möglich, hier Linq zu benutzen?

Thx!

+0

Gibt es eine Aus welchem ​​Grund möchten Sie LINQ hier verwenden? Was hast du bisher versucht? –

+0

Ich habe versucht, dies mit einer Schleife zu lösen (noch nicht fertig ...). Aber während ich die Schleife schrieb, sieht es für mich nicht wie eine elegante Lösung aus:/ – Weissvonnix

Antwort

4

Ausnutzen Nebenwirkungen (group) ist keine gute Praxis, kann aber hilfreich sein:

int[] list = { 5, 10, 15, 40, 45, 50, 70, 75 }; 

    int step = 5; 
    int group = 1; 

    var result = list 
    .Select((item, index) => new { 
       prior = index == 0 ? item : list[index - 1], 
       item = item, 
      }) 
    .GroupBy(pair => Math.Abs(pair.prior - pair.item) <= step ? group : ++group, 
      pair => pair.item); 

Test:

string report = string.Join(Environment.NewLine, result 
    .Select(chunk => String.Format("{0}: [{1}]", chunk.Key, String.Join(", ", chunk)))); 

Ergebnis:

1: [5, 10, 15] 
2: [40, 45, 50] 
3: [70, 75] 
2

Unter der Annahme, Sammlung hat einen Indexer definiert ist, kann so etwas wie dieses:

const int step = 5; 
int currentGroup = 1; 
var groups = list.Select((item, index) => 
{ 
    if (index > 0 && item - step > list[index - 1]) 
    { 
     currentGroup++; 
    } 
    return new {Group = currentGroup, Item = item}; 
}).GroupBy(i => i.Group).ToList(); 
2

Meiner Meinung nach, schreiben Sie einfach eine Funktion, es zu tun. Dies ist leichter zu verstehen und besser lesbar als die Linq-Beispiele in anderen Antworten.

public static List<List<int>> Group(this IEnumerable<int> sequence, int groupDiff) { 
    var groups = new List<List<int>>(); 
    List<int> currGroup = null; 
    int? lastItem = null; 
    foreach (var item in sequence) { 
     if (lastItem == null || item - lastItem.Value > groupDiff) { 
      currGroup = new List<int>{ item }; 
      groups.Add(currGroup); 
     } else { 
      // add item to current group 
      currGroup.Add(item); 
     } 
     lastItem = item; 
    } 
    return groups; 
} 

Und wie diese Annahme

List<List<int>> groups = Group(list, 5); 

nennen: list wird sortiert. Wenn es nicht sortiert ist, sortieren Sie es zuerst und verwenden Sie den obigen Code.

Auch: wenn Sie groups zu einem int[][] benötigen, verwenden Sie einfach die Linq-Methode ToArray() nach Ihren Wünschen.

+0

Ich denke, dass die Lesbarkeit vom Programmierer abhängt. Je mehr ich mit Lambda-Funktionen arbeite, desto leichter ist es für mich zu lesen. – Weissvonnix

Verwandte Themen