2016-06-23 7 views
1

Ich möchte überprüfen, dass eine Zeichenfolge keine doppelten Zeichen (aus einer Reihe von schlechten Zeichen) in benachbarten Positionen enthält. Zurück Stapelüberlauf Antworten zu diesem Thema scheinen hauptsächlich von der allgemeinen Form zu sein:Ist es möglich, LINQ zu verwenden, um doppelte benachbarte Zeichen zu erkennen?

for(int i = 0; i < testString.Length-1; i++){ 
    if(testString[i] == testString[i+1] && testString[i] == badChar){ 
     //Handle rejection here 
    } 
} 

Ist es möglich, diese Art der Überprüfung/Validierung in LINQ zu tun? Allgemeiner: Ist es innerhalb von LINQ möglich, den Wert jedes Zeichens in einer Zeichenkette mit dem nächsten Zeichen in einem

testString.Any(c => /*test goes here*/) Aufruf zu vergleichen?

+2

Blick auf die [MoreLINQ Bibliothek] (https://github.com/morelinq/MoreLINQ), insbesondere [ 'GroupAdjacent'] (https://github.com/morelinq/MoreLINQ/blob/master/ MoreLinq/GroupAdjacent.cs) - Sie können die Tests [hier] (https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq.Test/GroupAdjacentTest.cs) für Beispiele sehen. (Wenn Sie die Bibliothek nicht selbst verwenden möchten, zeigt sie Ihnen zumindest, wie es geht.) – davidbak

+1

Alternativ könnte regex für Sie arbeiten. – Derek

+1

Regex können Sie nur ([Badschar]) \ 1 –

Antwort

4

Immer, wenn Sie eine Klasse, die Count (oder gleichwertig) Eigentum und Indexer hat, können Sie Enumerable.Range als Basis für die LINQ-Abfrage verwenden und innerhalb eines indizierten Zugriff ähnlich den nicht LINQ Code ausführen:

bool test = Enumerable.Range(0, testString.Length - 1).Any(i = > 
     testString[i] == testString[i + 1] && testString[i] == badChar) 
+0

Ich habe dies markiert, weil es am ehesten dem ursprünglich Gewünschten entspricht, aber da es der Loop-Methode sowieso so ähnlich ist, denke ich, dass ich wahrscheinlich nur damit anfangen werde. –

5

Sie könnten Pairwise aus moreLINQ Bibliothek verwenden:

if(testString.Pairwise((n, m) => new {n, m}).Any(x => x.n == x.m && x.n == badChar)) 
    // do something 

Wenn Sie reine LINQ verwenden möchten Sie es mit Skip/Zip Kombination hacken könnte:

if(testString.Zip(testString.Skip(1), (n, m) => new {n, m})).Any(x => x.n == x.m && x.n == badChar)) 
    // do something 

Aber diese beiden Lösungen wird viel sein langsamer als for Loop-basierte Lösung, so würde ich dagegen raten.

+0

_Das ist, was ich in meinem Kommentar oben gesucht habe - ich _knew_ moreLINQ hatte etwas speziell dafür gebaut. – davidbak

3

Wie wäre es mit dem ungeheuerlichen Missbrauch der Aggregatfunktion? Ich denke gerne, dass diese Antwort eher ein Beispiel dafür ist, was nicht zu tun ist, selbst wenn es möglich ist. Eine Weile und string.indexOf sind wahrscheinlich am besten für dieses Problem geeignet.

var items = "ab^cdeef##gg"; 
var badChars = new[] {'^', '#', '~'}; 
var doesAdjacentDupeExist = false; 
var meaninglessAggregate = items.Aggregate((last, current) => 
    { 
     if (last == current && badChars.Contains(last)) 
     { 
      doesAdjacentDupeExist = true; 
     }; 
     return current; 
    }); 

Dies ist nicht so clever, aber es funktioniert. Es handelt die Einstellung einer externen Variable innerhalb der Abfrage (schlecht), um auf index und elementAt (nicht groß) zu vertrauen.

var items = "abcdefffghhijjk"; 
var badChars = new[] { 'f', 'h' }; 
var indexCieling = items.Count() - 1; 
var badCharIndexes = items.Select((item, index) => 
    { 
     if (index >= indexCieling) 
     { 
      return null as int?; 
     } 
     else 
     { 
      if (item == items.ElementAt(index + 1) && badChars.Contains(item)) 
      { 
       return index as int?; 
      } 
      else 
      { 
       return null as int?; 
      } 
     } 
    }); 
var doesAdjacentDupeExist = badCharIndexes.Any(x => x.HasValue); 
+0

engenius ....... –

Verwandte Themen