web-dev-qa-db-ja.com

StringBuilderの最速の検索メソッド

コース名を保存するために使用されるstb_Swap_Tabuという名前のStringBuilderがあります。次の方法を使用して、コースを検索しています。

stb_Swap_Tabu.ToString.Contains("CourseName")

私の場合、パフォーマンスが最も重要な問題です。もっと速い方法はありますか?

13
Alaa

StringBuilderは、実際にはすべての文字列の目的を意図したものではありませんでした。本当に検索する必要がある場合は、独自のメソッドを作成する必要があります。

さまざまなケースに適した文字列検索アルゴリズムがいくつかあります。

以下は、序数の一致のみを考慮したKnuth–Morris–Prattアルゴリズムの単純な実装です(大文字と小文字の区別、カルチャ関連の照合、単純なコードポイントとコードポイントの一致のみ)。初期のΘ(m)オーバーヘッドがあります。ここでmは検索される単語の長さであり、次にΘ(n)で見つかります。ここでnは求められる単語、または文字列ビルダー全体の長さ(存在しない場合)。これは、Θ((n-m+1) m)である単純な文字ごとの比較よりも優れています(O()表記は上限を表し、Θ()は上限と下限の両方を表します)。

とはいえ、リストを作成する方が手元のタスクへのより良いアプローチかもしれないように思えます。

public static class StringBuilderSearching
{
  public static bool Contains(this StringBuilder haystack, string needle)
  {
    return haystack.IndexOf(needle) != -1;
  }
  public static int IndexOf(this StringBuilder haystack, string needle)
  {
    if(haystack == null || needle == null)
      throw new ArgumentNullException();
    if(needle.Length == 0)
      return 0;//empty strings are everywhere!
    if(needle.Length == 1)//can't beat just spinning through for it
    {
      char c = needle[0];
      for(int idx = 0; idx != haystack.Length; ++idx)
        if(haystack[idx] == c)
          return idx;
      return -1;
    }
    int m = 0;
    int i = 0;
    int[] T = KMPTable(needle);
    while(m + i < haystack.Length)
    {
      if(needle[i] == haystack[m + i])
      {
        if(i == needle.Length - 1)
          return m == needle.Length ? -1 : m;//match -1 = failure to find conventional in .NET
        ++i;
      }
      else
      {
        m = m + i - T[i];
        i = T[i] > -1 ? T[i] : 0;
      }
    }
    return -1;
  }      
  private static int[] KMPTable(string sought)
  {
    int[] table = new int[sought.Length];
    int pos = 2;
    int cnd = 0;
    table[0] = -1;
    table[1] = 0;
    while(pos < table.Length)
      if(sought[pos - 1] == sought[cnd])
        table[pos++] = ++cnd;
      else if(cnd > 0)
        cnd = table[cnd];
      else
        table[pos++] = 0;
    return table;
  }
}
27
Jon Hanna

これは古い質問ですが、自分のプロジェクトのソリューションを作成しようとしたときに検索結果に表示されました。 StringBuilder.ToStringのメソッド結果を検索する必要があると思いましたが、StringBuilder自体でメソッドを呼び出すことができることに気付きました。私の状況はあなたの状況と同じではないかもしれませんが、私は共有したいと思います:

Private Function valueFormatter(ByVal value As String) As String
    ' This will correct any formatting to make the value valid for a CSV format
    '
    ' 1) Any value that as a , in it then it must be wrapped in a " i.e. Hello,World -> "Hello,World"
    ' 2) In order to escape a " in the value add a " i.e. Hello"World -> Hello""World
    ' 3) if the value has a " in it then it must also be wrapped in a " i.e. "Hello World" -> ""Hello World"" -> """Hello World"""
    ' 
    ' VB NOTATAION 
    ' " -> """"
    ' "" -> """"""

    If value.Contains(",") Or value.Contains("""") Then
        Dim sb As New StringBuilder(value)
        If value.Contains("""") Then sb.Replace("""", """""")
        sb.Insert(0, """").Append("""")
        Return sb.ToString
    Else
        Return value
    End If
End Function