2016-04-01 5 views
0

プレースホルダの膨大な負荷(約250)をプレーンテキストで解決する必要があります。プレースホルダをプレーンテキストで解決するベストプラクティスは何ですか?

プレースホルダは、例は%電子メールの送信%なり、ThisIsAPlaceholder%%として定義されます。

これで少しばかげています。コードは大文字と小文字を区別しないプレースホルダも処理する必要があります。したがって、%EmailSender%,%EMAILSENDER%および%emailsender%は同じプレースホルダです。私はそれが複雑になるところだと思う。あなたが気づくこととして、私はケースinsesitiveプレースホルダを扱うことができない

public string ResolvePlaceholders(string text) 
{ 
    var placeholders = new IEnumerable<string> 
    { 
     "%EmailSender%", 
     "%ErrorMessage%", 
     "%ActiveUser%" 
    }; 

    var resolvedText = text; 

    foreach(var placeholder in placeholders) 
    { 
     if(!replacedText.Contains(placeholder)) 
      continue; 

     var value = GetValueByPlaceholder(placeholder); 

     resolvedText = resolvedText.Replace(placeholder, value); 
    } 


    return resolvedText; 
} 

しかし..:

私の最初のアプローチは、のようなものでした。 また、すべてのプレースホルダ(テキストで使用されている場合)を確認します。私は約10,000語のテキストで> 200台のプラットホルダーを使用すると、この解決策はあまり速くないと思います。

どのようにこれをより良い方法で解決できますか?大文字と小文字を区別しないプレースホルダをサポートするソリューションが評価されます。

+0

[文字列形式のカスタム文字列プレースホルダを提供する方法](http://stackoverflow.com/questions/1102300/how-to-provide-custom-string-placeholder-for-string-format) –

答えて

1

に答えて、本当に基本的なものの、効率的な交換スキームのようなものになりますようですこれは:

private readonly static Regex regex = new Regex("%(?<name>.+?)%"); 

private static string Replace(string input, ISet<string> replacements) 
{ 
    string result = regex.Replace(input, m => { 

     string name = m.Groups["name"].Value; 
     string value; 
     if (replacements.Contains(name)) 
     { 
      return GetValueByPlaceholder(name); 
     } 
     else 
     { 
      return m.Captures[0].Value; 
     } 
    }); 

    return result; 
} 

public static void Main(string[] args) 
{ 
    var replacements = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase) 
    { 
     "EmailSender", "ErrorMessage", "ActiveUser" 
    }; 

    string text = "Hello %ACTIVEUSER%, There is a message from %emailsender%. %errorMessage%"; 
    string result = Replace(text, replacements); 

    Console.WriteLine(result); 
} 

正規表現を使用して入力テキストを1回読み込みます。我々がMainで構築したHashSetに渡された等価比較器を介して大文字小文字を区別しない比較を行っていることに注意してください。認識できない項目は無視されます。より一般的なケースでは、Replace方法は、辞書を取ることができる:

private static string Replace(string input, IDictionary<string, string> replacements) 
{ 
    string result = regex.Replace(input, m => { 

     string name = m.Groups["name"].Value; 
     string value; 
     if (replacements.TryGetValue(name, out value)) 
     { 
      return value; 
     } 
     else 
     { 
      return m.Captures[0].Value; 
     } 
    }); 

    return result; 
} 

信頼できないソース(インターネット上などのユーザー)からの入力に使用した数量に一致する正規表現の一致のタイムアウトを指定することで、一般的な勧告を。あなたはスローされたRegexMatchTimeoutExceptionをキャッチし、その場合何かをしなければならないでしょう。

0

正規表現ソリューション

private static string ReplaceCaseInsensitive(string input, string search, string replacement) 
{ 
    string result = Regex.Replace(
     input, 
     Regex.Escape(search), 
     replacement.Replace("$","$$"), 
     RegexOptions.IgnoreCase 
    ); 
    return result; 
} 

非正規表現のソリューション

public static string Replace(this string str, string old, string @new, StringComparison comparison) 
{ 
    @new = @new ?? ""; 
    if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(old) || old.Equals(@new, comparison)) 
    return str; 
    int foundAt; 
    while ((foundAt = str.IndexOf(old, 0, StringComparison.CurrentCultureIgnoreCase)) != -1) 
    str = str.Remove(foundAt, old.Length).Insert(foundAt, @new); 
    return str; 
} 

は、あなたのケースの重複質問のように/ String.Replace ignoring case

関連する問題