1. ホーム
  2. c#

[解決済み】大文字の前にスペースを追加する

2022-04-10 04:25:16

質問

ThisStringHasNoSpacesButItDoesHaveCapitals"という文字列がある場合、大文字の前にスペースを追加する最も良い方法は何ですか?つまり、最後の文字列は "This String Has No Spaces But It Does Have Capitals".となります。

以下は、RegExを使った私の試みです。

System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")

解決方法は?

正規表現はうまくいきますが(私はMartin Brownsの回答に投票しました)、高価です(そして個人的には、数文字より長いパターンは法外に鈍重だと思います)。

この関数

string AddSpacesToSentence(string text, bool preserveAcronyms)
{
        if (string.IsNullOrWhiteSpace(text))
           return string.Empty;
        StringBuilder newText = new StringBuilder(text.Length * 2);
        newText.Append(text[0]);
        for (int i = 1; i < text.Length; i++)
        {
            if (char.IsUpper(text[i]))
                if ((text[i - 1] != ' ' && !char.IsUpper(text[i - 1])) ||
                    (preserveAcronyms && char.IsUpper(text[i - 1]) && 
                     i < text.Length - 1 && !char.IsUpper(text[i + 1])))
                    newText.Append(' ');
            newText.Append(text[i]);
        }
        return newText.ToString();
}

100,000回を2,968,750ティックで実行し、正規表現は25,000,000ティックかかります(これは正規表現をコンパイルした場合です)。

しかし、メンテナンスのためのコードが多くなります。

お役に立てれば幸いです :)

更新情報

久しぶりに見たら、コードが変わってからタイミングが更新されていないことに今気づきました(少ししか変わっていない)。

Abbbbbbb'が100回繰り返される文字列(つまり1,000バイト)の場合、10万回の変換を実行するとハンドコード関数は4,517,177ティック、下のRegexは59,435,719で、ハンドコード関数はRegexにかかる時間の7.6%で実行できることになります。

アップデート2 頭字語は考慮されるのでしょうか?対応します if文のロジックはかなり曖昧ですが、これを展開するとこんな感じになります。

if (char.IsUpper(text[i]))
    if (char.IsUpper(text[i - 1]))
        if (preserveAcronyms && i < text.Length - 1 && !char.IsUpper(text[i + 1]))
            newText.Append(' ');
        else ;
    else if (text[i - 1] != ' ')
        newText.Append(' ');

...は全く役に立ちません!

以下は、オリジナルの シンプル メソッドは、頭文字を気にすることなく使用できます。

string AddSpacesToSentence(string text)
{
        if (string.IsNullOrWhiteSpace(text))
           return "";
        StringBuilder newText = new StringBuilder(text.Length * 2);
        newText.Append(text[0]);
        for (int i = 1; i < text.Length; i++)
        {
            if (char.IsUpper(text[i]) && text[i - 1] != ' ')
                newText.Append(' ');
            newText.Append(text[i]);
        }
        return newText.ToString();
}