2011-01-02 18 views
11

文字列内の文字の3番目のインデックスを取得できるコマンドはありますか?例:上記の文章、私は3番目のコロンのインデックスを作成するには文字列内の文字の3番目のインデックス

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

、私はそれを行うことができますどのように10の隣に1?私はstring.IndexOfとstring.LastIndexOfを知っていますが、この場合、3回目の使用時に文字のインデックスを取得します。

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

たぶん、いくつかの正規表現? http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.aspx –

+0

3番目のコロンの後の文字列の内容なら、おそらくコロンで文字列を分割して結合するだけでよい最初の3つのトークン以外何も...? – jishi

+0

@jishi:私はまた、インデックスを使用して別の何かが必要でした。 – Iceyoshi

答えて

13

String.IndexOfが最初のインデックスを取得しますが、開始点を与えるオーバーロードがあります。したがって、最初のIndexOfの結果と次のものの開始点として1つの結果を使用することができます。そして、ちょうどインデックスを蓄積するのに十分な回数:あなたはmyStringは、少なくとも3つのコロンが含まれていることを知っている限り

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

は、エラー処理を追加します。

+0

私が追加する唯一のことは 'IndexOf'(' Index'をタイプしたことに注意してください)を呼び出すたびに 'offset'が非負であることをチェックし、' firstOffset'という名前の呼び出しのたびに別の変数を使います。それぞれ「secondOffset」と「thirdOffset」となります。いくつかはこの過度のことを考慮するが、悪い飼い慣らしの習慣に抵抗するだけである。 – jason

+0

@Jason: 'Index' - >' IndexOf':修正。最終的なメモを参照してください。 -1の結果をチェックします。そして、ここでは3つの別々の変数が残念だと思っています(私が知っていれば、十分な文字があって1つの表現ですべてを行うことができましたが、コンパクトコードが好きです。 – Richard

+0

これは、n番目のインデックスを取得するのに非常に良い方法です。はい、文字列には少なくとも3つのコロンが含まれているので、このコードに問題はないはずです。 – Iceyoshi

9

次のようなものを書くことができ、次のように明らかにあなたはそれを使用する必要がありますあなたはそれを3回呼び出すべきです(しかし、それぞれの呼び出しの後に、何かが見つかったかどうかも確認する必要があります)。

+1

文字列に1文字または2文字しかない場合はどうなりますか? if(index <0)return indexを追加する必要があります。 –

0

あなたは.IndexOf(CHAR、位置)を呼び出すことができますから検索する:

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

+0

ええ、それは私がやったことです、それはうまくいく(誰かが投稿したコードのおかげで)。 – Iceyoshi

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

あなたは、その文字列を別の部分に解析したいと思っています。

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

ええ、それは私がやりたいことです(私は今それをやったことがあります)が、4の代わりに3つのコロン(エラーメッセージには1つも含まれない)がある可能性があります。その場合、カウントはさまざまで、この問題をどのように克服できたかはわかりません。 – Iceyoshi

+0

count = 4は、_upから_4文字列までを取得することを意味します。最後の文字列には、分割されずにセパレータが含まれることがあります。私の例では、区切り記号として ":"を使用しているが、メッセージに ":"が含まれていても分割されていないと表示されていないことがわかります。 – sisve

+0

私は、メッセージ・テキストに分割されていないことを示すために ":"が含まれるようにサンプル・コードを変更しました。 – sisve

0

少し醜いが、作品(すでに掲載他人に)別のアプローチ:

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

これは、すでにいくつかの非常に良い方法に答えてきた - しかし、私は試してみて、それを書くことにしました式を使用します。

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

ともそれを証明するためのテスト:ここ

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

再帰的実装(文字列をchar型ではない)である - フレームワーク方法(単数または複数)の形式を模倣、拡張メソッドとして。

拡張メソッドで '文字列値'を 'char値'に変更し、それに応じてテストを更新するだけで済みます。興味があれば投稿してもらえます?

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

また、ここであなたを助けるかもしれないいくつかの(MbUnitの)ユニットテスト(それが正しいことを証明するために)、次のとおりです。

[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

同様の質問にこの答えをご覧ください。 https://stackoverflow.com/a/46460083/7673306
それは、指定された文字列内の特定の文字のn番目の出現のインデックスを見つける方法を提供します。

あなたの特定のケースでは、そのように実装されるだろう:

int index = IndexOfNthCharacter("error: file.ext: line 10: invalid command [test:)]", 3, ':'); 
関連する問題