2011-01-02 17 views
11

Gibt es einen Befehl, der den dritten Index eines Zeichens in einer Zeichenkette erhalten kann? Zum Beispiel:C# dritter Index eines Zeichens in einer Zeichenkette

error: file.ext: line 10: invalid command [test:)] 

In dem obigen Satz, ich möchte den Index des dritten Doppelpunkt, das eine neben dem 10. Wie könnte ich das tun? Ich weiß von string.IndexOf und string.LastIndexOf, aber in diesem Fall möchte ich den Index eines Zeichens erhalten, wenn es das dritte Mal verwendet wird.

+2

Vielleicht:

In Ihrem speziellen Fall, es wäre wie so umgesetzt werden? http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.aspx –

+0

Wenn es der Inhalt der Zeichenfolge nach dem 3. Doppelpunkt ist, nach dem Sie suchen, sollten Sie die Zeichenfolge einfach auf Doppelpunkt aufteilen und beitreten alles außer den ersten 3 Tokens ...? – jishi

+0

@jishi: Ich brauchte auch etwas anderes mit dem Index. – Iceyoshi

Antwort

13

String.IndexOf werden Sie den Index des ersten, aber hat Überlastungen einen Ausgangspunkt zu geben. Sie können also das Ergebnis der ersten IndexOf plus eins als Ausgangspunkt für die nächste verwenden. Und dann sammeln sich nur Indizes eine ausreichende Anzahl von Malen:

var offset = myString.IndexOf(':'); 
offset = myString.IndexOf(':', offset+1); 
var result = myString.IndexOf(':', offset+1); 

hinzufügen Fehlerbehandlung, wenn Sie wissen, dass myString mindestens drei Doppelpunkte.

+0

Die einzige Sache, die ich hinzufügen würde, ist überprüft, dass "offset" nicht negativ ist nach jedem Aufruf von 'IndexOf' (beachten Sie, dass Sie' Index' eingegeben haben), und ich würde eine andere Variable nach jedem Aufruf mit dem Namen 'firstOffset',' secondOffset' bzw. 'thirdOffset'. Einige werden dieses Overkill in Betracht ziehen, aber sie widerstehen nur schlecht eingefahrenen Gewohnheiten. – jason

+0

@Jason: 'Index' ->' IndexOf': Fixierung. Siehe letzte Anmerkung zu. prüft auf -1 Ergebnis. Und ich denke, dass drei separate Variablen hier zuviel sind (wenn ich wüsste, dass genügend Zeichen vorhanden sind, würde ich das ganze in einem Ausdruck machen. Aber dann mag ich kompakten Code, da er oft besser lesbar ist, wenn man Rauschen entfernt). – Richard

+0

Dies ist eine ziemlich gute Methode, um den n-ten Index zu erhalten. Und ja, die Zeichenfolge enthält immer mindestens 3 Doppelpunkte, also sollte es kein Problem mit diesem Code geben. – Iceyoshi

9

Sie schreiben könnte so etwas wie:

public static int CustomIndexOf(this string source, char toFind, int position) 
    { 
     int index = -1; 
     for (int i = 0; i < position; i++) 
     { 
      index = source.IndexOf(toFind, index + 1); 

      if (index == -1) 
       break; 
     } 

     return index; 
    } 

EDIT: Offensichtlich haben Sie es wie folgt zu verwenden:

int colonPosition = myString.CustomIndexOf(',', 3); 
+1

Was ist, wenn nur 1 oder 2 Zeichen in der Zeichenfolge stehen? Sie sollten hinzufügen, wenn (Index <0) Index zurückgeben; –

0

Sie können .IndexOf nennen (char, Position) aus suchen gewünschte Position, also sollten Sie es dreimal aufrufen (aber nach jedem Anruf sollten Sie auch prüfen, ob etwas gefunden wurde).

+0

Ja, das habe ich gemacht und es funktioniert gut (danke an einen anderen Code, den jemand gepostet hat). – Iceyoshi

0
int pos = -1; 
for (int k = 0; k < 3; ++k) 
{ 
    pos = s.indexOf(':', pos+1); 
    // Check if pos < 0... 
} 
4

Ich vermute, dass Sie diese Zeichenfolge in verschiedene Teile analysieren möchten.

public static void Main() { 
    var input = @"error: file.ext: line 10: invalid command [test (: ]"; 
    var splitted = input .Split(separator: new[] {": "}, count: 4, options: StringSplitOptions.None); 

    var severity = splitted[0]; // "error" 
    var filename = splitted[1]; // "file.ext" 
    var line = splitted[2];  // "line 10" 
    var message = splitted[3]; // "invalid command [test (: ]" 
} 
+0

Ja, es ist, was ich tun möchte (nun, ich habe es jetzt getan), aber es gibt eine Möglichkeit, dass es nur 3 Doppelpunkte statt 4 geben könnte (die Fehlermeldung würde keine enthalten), und ebenso könnte es mehr geben. In diesem Fall würde die Anzahl variieren und ich bin mir nicht sicher, wie ich dieses Problem überwinden könnte. – Iceyoshi

+0

count = 4 bedeutet, dass Sie _up to_ 4 strings abrufen. Die letzte Zeichenfolge kann das Trennzeichen enthalten, ohne aufgeteilt zu werden. Ich weiß, mein Beispiel zeigt das nicht, da ich ":" als Trennzeichen verwende, aber wenn die Nachricht ":" enthalten würde, wäre es immer noch nicht geteilt worden. – sisve

+0

Ich habe den Beispielcode geändert, sodass der Nachrichtentext ":" enthält, um anzuzeigen, dass er nicht geteilt wurde. – sisve

0

Ein wenig hässlich, aber ein alternativer Ansatz (zu den anderen bereits gebucht), das funktioniert:

public int FindThirdColonIndex(string msg) 
{  
    for (int i = 0, colonCount = 0; i < msg.Length; i++) 
    { 
     if (msg[i] == ':' && ++colonCount == 3) { return i; } 
    } 

    // Not found 
    return -1; 
} 
2

Dieses bereits mehrere sehr gute Möglichkeiten beantwortet wurde - aber ich beschloss, es zu versuchen und schreiben Ausdrücke verwenden.

private int? GetNthOccurrance(string inputString, char charToFind, int occurranceToFind) 
{ 
    int totalOccurrances = inputString.ToCharArray().Count(c => c == charToFind); 
    if (totalOccurrances < occurranceToFind || occurranceToFind <= 0) 
    { 
     return null; 
    } 

    var charIndex = 
     Enumerable.Range(0, inputString.Length - 1) 
      .Select(r => new { Position = r, Char = inputString[r], Count = 1 }) 
      .Where(r => r.Char == charToFind); 


    return charIndex 
     .Select(c => new 
     { 
      c.Position, 
      c.Char, 
      Count = charIndex.Count(c2 => c2.Position <= c.Position) 
     }) 
     .Where(r => r.Count == occurranceToFind) 
     .Select(r => r.Position) 
     .First(); 
} 

und Tests, es auch zu beweisen:

Assert.AreEqual(0, GetNthOccurrance(input, 'h', 1)); 
Assert.AreEqual(3, GetNthOccurrance(input, 'l', 2)); 
Assert.IsNull(GetNthOccurrance(input, 'z', 1)); 
Assert.IsNull(GetNthOccurrance(input, 'h', 10)); 
0

Hier ist eine rekursive Implementierung ist (für String nicht char) - als Erweiterung Methode, um das Format der Rahmen Methode nachahmt (n).

Alles, was Sie tun müssen, ist 'Zeichenfolge Wert' in 'char Wert' in der Erweiterungsmethode zu ändern und die Tests entsprechend zu aktualisieren, und es wird funktionieren ... Ich bin glücklich, das zu tun und es zu veröffentlichen, wenn jemand interessiert ist ?

public static int IndexOfNth(
    this string input, string value, int startIndex, int nth) 
{ 
    if (nth < 1) 
     throw new NotSupportedException("Param 'nth' must be greater than 0!"); 
    if (nth == 1) 
     input.IndexOf(value, startIndex); 
    return 
     input.IndexOfNth(value, input.IndexOf(value, startIndex) + 1, --nth); 
} 

Auch hier sind einige (MBUnit) Unit-Tests, die Ihnen helfen (um zu beweisen, es ist richtig):

[Test] 
public void TestIndexOfNthWorksForNth1() 
{ 
    const string input = "foo<br />bar<br />baz<br />"; 
    Assert.AreEqual(3, input.IndexOfNth("<br />", 0, 1)); 
} 

[Test] 
public void TestIndexOfNthWorksForNth2() 
{ 
    const string input = "foo<br />whatthedeuce<br />kthxbai<br />"; 
    Assert.AreEqual(21, input.IndexOfNth("<br />", 0, 2)); 
} 

[Test] 
public void TestIndexOfNthWorksForNth3() 
{ 
    const string input = "foo<br />whatthedeuce<br />kthxbai<br />"; 
    Assert.AreEqual(34, input.IndexOfNth("<br />", 0, 3)); 
} 
0

Bitte beachten Sie diese Antwort auf eine ähnliche Frage: https://stackoverflow.com/a/46460083/7673306
Es stellt eine Methode zur Verfügung, mit der Sie den Index des n. Auftretens eines bestimmten Zeichens innerhalb einer angegebenen Zeichenfolge finden können.
einige reguläre Ausdrücke

int index = IndexOfNthCharacter("error: file.ext: line 10: invalid command [test:)]", 3, ':'); 
Verwandte Themen