2013-07-18 13 views
7

In C# wird durch Aufrufen der .Split-Methode eine Zeichenfolge in ein Array von Zeichenfolgen basierend auf einem Zeichen oder einer Zeichenfolge aufgeteilt.Gibt es eine "Split List" -Methode in C#?

Gibt es eine äquivalente Methode für Listen oder Arrays?

Zum Beispiel:

var foo = new List<int>() { 1, 2, 3, 0, 4, 5, 0, 6 }; 
var output = Split(foo, 0); 
// produces { { 1, 2, 3 }, { 4, 5 }, { 6 } } 

Das ist, was ich bisher habe - gibt es einen Reiniger oder beredte Weise die gleiche Aufgabe zu erledigen?

IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> list, T divider) 
{ 
    var output = new List<List<T>>(); 
    var temp = new List<T>(); 
    foreach (var item in list) 
    { 
     if (item.Equals(divider)) 
     { 
      output.Add(temp); 
      temp = new List<T>(); 
     } 
     else 
     { 
      temp.Add(item); 
     } 
    } 

    output.Add(temp); 
    return output; 
} 

Edit:

Es ist einfach fiel mir ein, dass meine Version nur die Liste geteilt wird durch ein einzelnes Element, während string.Split aufspalten kann entweder ein einzelnes Zeichen oder eine beliebige Zeichenfolge verwenden.

Nur der Vollständigkeit halber, was wäre der beste Weg, das zu implementieren?

+1

Sie könnten in der Lage sein, etwas mit IndexOf zu tun, obwohl ich nicht sicher bin, wie die Gleichheit im Allgemeinen vergleicht ... – Jeff

+0

Auf dem Bearbeiten - während mit Single-Separator ist ziemlich direkt, was ist "gut/besser" -Code, es ist nicht der Fall für übereinstimmende Sequenzen: Sie müssten richtig umgehen Misses während des Abgleichs ('aabbaba' Split auf' bab' erfordert eine Form des erneuten Besuchs zuerst 'b' zu (es zurückgeben) mit unterschiedlichen Kompromissen bei mehreren Ansätzen dazu. Es gibt auch viele verschiedene String-Matching-Algorithmen (die genau in Ihrem Edit sind), die für verschiedene Kriterien optimieren. Edit ist also nicht wirklich zu verantworten (im Sinne von "das Beste"). –

+0

mögliche Duplikate von [Gruppe nach Element in Linq] (http://stackoverflow.com/questions/3759123/group-by-element-in-linq) – nawfal

Antwort

8

Kein Einbau-äquivalent, aber ein fauler bewertet würde man

IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> list, T divider) 
{ 
    var temp = new List<T>(); 
    foreach (var item in list) 
    { 
     if (!item.Equals(divider)) 
     { 
      temp.Add(item); 
     } 
     else 
     { 
      yield return temp; 
      temp = new List<T>(); 
     } 
    } 

    if(temp.Count>0) yield return temp; 
} 
2

Nein, es ist keine speziellen bestehenden Verfahren im Rahmen Sequenz zu spalten.

Sie Code ist vernünftig.

Routen zu verbessern/ändern:

  • Sie können möglicherweise yield return statt zu output Hinzufügen verwenden, um einige faule Auswertung zu gewinnen.
  • Mit noch interessanterem Code können Sie auch innere Listen faul machen (was wichtig sein kann, wenn die eingehende Sequenz nicht gebunden ist/zu lange Segmente).
  • Und Sie können mit Aggregate, wenn Sie einzelne Anweisung Code zeigen wollen ...
0

Sie wissen nicht, jeder integrierte Funktion. Allerdings würde ich prüfen, dies zu tun:

public static IEnumerable<List<int>> Split(List<int> list, int delimiter) 
{ 
    var start = 0; 
    foreach (var end in list.FindAll(x => x == delimiter).Select(splitter => list.IndexOf(splitter, start))) 
    { 
     yield return list.GetRange(start, end - start); 

     start = end + 1; 
    } 

    if (start <= list.Count) 
    { 
     yield return list.GetRange(start, list.Count - start); 
    } 
} 
+0

Nicht sicher, das ist wirklich eine Verbesserung gegenüber der Op-Methode ... es könnte lesbarer sein, erfordert aber auch (?) mehrere Durchläufe über die Eingabe. – McGarnagle

+0

Und es würde nicht funktionieren, wenn die 'liste'' IEnumerable 'nicht' List '(wegen * GetRange *) ist – I4V

Verwandte Themen