9

たとえば、置換を行うために使用する必要がある一連の文があります。

abc => cde
ab df => de
...

そして、私はどこに変更を加えるかというテキストを持っています。ただし、そのテキストのケースを事前に知る方法はありません。たとえば、私が持っている場合:

A bgt abc hyi. Abc Ab df h

交換して取得する必要があります:

A bgt cde nyi. Cde De h

または、できるだけそれに近い、つまりケースを保持する

編集:私はこれについて多くの混乱を見ているので、少し明確にしようとします:

交換後にキャップを保持する方法について尋ねていますが、それがうまく通過したとは思わないので(何が必要かを十分に説明していません)、実際の言葉を使用してより現実的な例を挙げます。

いわば同義語で表現を置き換えるゴサリーのように考えてください。マップすると:

didn't achieve success => failled miserably

次に、入力として設定を取得します。

As he didn't achieve success, he was fired

私は得るだろう

As he failled miserably, he was fired

しかし、didd が大文字でなかった場合は失敗し、achieve または success が大文字で示された場合は悲惨なことになり、1 つ以上の文字が大文字である場合は、対応する文字も同様になります。

私の主な可能性は(私が本当に考慮したいもの)です

  • 最初の単語の最初の文字のみ大文字
  • 大文字のすべての単語の最初の文字のみ
  • すべて大文字

すでに受け入れられるこれらの3つを処理できれば、それはより簡単なものだと思います-もちろん、利用可能であれば、より詳細なソリューションがより良いでしょう

何か案は?

4

5 に答える 5

4

これがうまくいくかどうかはわかりませんが、これが私が思いついたものです:

        string input = "A bgt abc hyi. Abc Ab df h";
        Dictionary<string, string> map = new Dictionary<string, string>();
        map.Add("abc", "cde");
        map.Add("ab df", "de");

        string temp = input;
        foreach (var entry in map)
        {
            string key = entry.Key;
            string value = entry.Value;
            temp = Regex.Replace(temp, key, match =>
            {
                bool isUpper = char.IsUpper(match.Value[0]);

                char[] result = value.ToCharArray();
                result[0] = isUpper
                    ? char.ToUpper(result[0])
                    : char.ToLower(result[0]);
                return new string(result);
            }, RegexOptions.IgnoreCase);
        }
        label1.Text = temp; // output is A bgt cde hyi. Cde De h

EDIT 変更された質問を読んだ後、ここに私の変更されたコードがあります(@Sephalliaのコードと同様の手順であることがわかります..および同様の変数名lol)

コードはもう少し複雑になりました..でも大丈夫だと思います

        string input = 
        @"As he didn't achieve success, he was fired.
        As he DIDN'T ACHIEVE SUCCESS, he was fired.
        As he Didn't Achieve Success, he was fired.
        As he Didn't achieve success, he was fired.";
        Dictionary<string, string> map = new Dictionary<string, string>();
        map.Add("didn't achieve success", "failed miserably");


        string temp = input;
        foreach (var entry in map)
        {
            string key = entry.Key;
            string value = entry.Value;
            temp = Regex.Replace(temp, key, match =>
            {
                bool isFirstUpper, isEachUpper, isAllUpper;

                string sentence = match.Value;
                char[] sentenceArray = sentence.ToCharArray();

                string[] words = sentence.Split(' ');

                isFirstUpper = char.IsUpper(sentenceArray[0]);

                isEachUpper = words.All(w => char.IsUpper(w[0]) || !char.IsLetter(w[0]));

                isAllUpper = sentenceArray.All(c => char.IsUpper(c) || !char.IsLetter(c));

                if (isAllUpper)
                    return value.ToUpper();

                if (isEachUpper)
                {
                    // capitalize first of each word... use regex again :P
                    string capitalized = Regex.Replace(value, @"\b\w", charMatch => charMatch.Value.ToUpper());
                    return capitalized;
                }


                char[] result = value.ToCharArray();
                result[0] = isFirstUpper
                    ? char.ToUpper(result[0])
                    : char.ToLower(result[0]);
                return new string(result);
            }, RegexOptions.IgnoreCase);
        }
        textBox1.Text = temp; 
        /* output is :
        As he failed miserably, he was fired.
        As he FAILED MISERABLY, he was fired.
        As he Failed Miserably, he was fired.
        As he Failed miserably, he was fired.
        */
于 2012-06-19T16:18:54.123 に答える
3

String.IndexOfStringComparison.CurrentCultureIgnoreCase指定して使用して、一致を見つけることができます。その時点で、文字ごとの置換はスワップを行うために機能します。大文字化はChar.IsUpper、ソース文字をチェックしてから、必要に応じて宛先でChar.ToUpperまたはChar.ToLowerを使用することで処理できます。

于 2012-06-19T15:57:02.150 に答える
2

String を文字の配列としてループし、Char.IsUpper(char parameter)を使用できます

  1. 空白文字列をインスタンス化する
  2. 文字をループするループを設定する
  3. キャラクターを別のキャラクターに変更する必要があるかどうかを確認します
    1. はい: 文字が大文字か小文字かを確認し、結果に応じて適切な文字を新しい文字列に入れます。
    2. いいえ: その文字を新しい文字列に入れるだけです
  4. 元の文字列を新しい文字列に設定します。

最も効率的で素晴らしい方法ではないかもしれませんが、シンプルで機能します。

余談ですが、文字をどのように変換しているかはわかりませんが、文字をアルファベットの下に(変換したい場合に)一定量シフトするとしたら、3シフトしているとしましょう. したがって、a -> d および E -> G などの場合、文字から ASCII 値を取得し、(変換する場合は) 3 を加算してから、ASCII 値から文字を取得できます。ここで説明したように。ただし、アルファベットの最後からループバックすることを確認するために、チェックを行う必要があります。(または、左にシフトしている場合は最初)。

編集#1:(上記をそのままにしておきます)

コードの本当に大きなブロック...申し訳ありません!これは、あなたが求めていたことを実行するための最良の方法でした。うまくいけば、誰かがよりエレガントな方法を考え出すかもしれません。説明が必要な場合は、コメントまたは何でもしてください。

    // (to be clear) This is Elias' (original) code modified.
    static void Main(string[] args)
    {
        string input = "As he DIDN'T ACHIEVE Success, he was fired";
        Dictionary<string, string> map = new Dictionary<string, string>();
        map.Add("didn't achieve success", "failed miserably");

        string temp = input;
        foreach (var entry in map)
        {
            string key = entry.Key;
            string value = entry.Value;
            temp = Regex.Replace(temp, key, match =>
            {
                string[] matchSplit = match.Value.Split(' ');
                string[] valueSplit = value.Split(' ');

                // Set the number of words to the lower one.
                // If they're the same, it doesn't matter.
                int numWords = (matchSplit.Length <= valueSplit.Length) 
                    ? matchSplit.Length
                    : valueSplit.Length;

                // only first letter of first word capitalized
                // only first letter of every word capitalized
                // all letters capitalized
                char[] result = value.ToCharArray(); ;
                for (int i = 0; i < numWords; i++)
                {
                    if (char.IsUpper(matchSplit[i][0]))
                    {
                        bool allIsUpper = true;
                        int c = 1;
                        while (allIsUpper && c < matchSplit[i].Length)
                        {
                            if (!char.IsUpper(matchSplit[i][c]) && char.IsLetter(matchSplit[i][c]))
                            {
                                allIsUpper = false;
                            }
                            c++;
                        }
                        // if all the letters of the current word are true, allIsUpper will be true.
                        int arrayPosition = ArrayPosition(i, valueSplit);
                        Console.WriteLine(arrayPosition);
                        if (allIsUpper)
                        {
                            for (int j = 0; j < valueSplit[i].Length; j++)
                            {
                                result[j + arrayPosition] = char.ToUpper(result[j + arrayPosition]);
                            }
                        }
                        else
                        {
                            // The first letter.
                            result[arrayPosition] = char.ToUpper(result[arrayPosition]);
                        }
                    }
                }

                return new string(result);
            }, RegexOptions.IgnoreCase);
        }
        Console.WriteLine(temp); 
    }

    public static int ArrayPosition(int i, string[] valueSplit)
    {
        if (i > 0)
        {
            return valueSplit[i-1].Length + 1 + ArrayPosition(i - 1, valueSplit);
        }
        else
        {
            return 0;
        }

        return 0;
    }
于 2012-06-19T16:07:42.980 に答える
0

一度に1文字ずつ置き換えて使用する

if(currentChar.ToString() == currentChar.ToUpper(currentChar).ToString())
{
   //replace with upper case variant 
}
于 2012-06-19T16:04:12.507 に答える
0

これはリードが言っていたこととほとんど同じです。Find唯一の秘訣は、とのReplace文字列が異なる長さの場合に何をすべきかわからないことです。だから私は最小の長さを選択し、それを使用しています...

static string ReplaceCaseInsensitive(string Text, string Find, string Replace)
{
    char[] NewText = Text.ToCharArray();
    int ReplaceLength = Math.Min(Find.Length, Replace.Length);

    int LastIndex = -1;
    while (true)
    {
        LastIndex = Text.IndexOf(Find, LastIndex + 1, StringComparison.CurrentCultureIgnoreCase);

        if (LastIndex == -1)
        {
            break;
        }
        else
        {
            for (int i = 0; i < ReplaceLength; i++)
            {
                if (char.IsUpper(Text[i + LastIndex])) 
                    NewText[i + LastIndex] = char.ToUpper(Replace[i]);
                else
                    NewText[i + LastIndex] = char.ToLower(Replace[i]);
            }
        }
    }

    return new string(NewText);
}
于 2012-06-19T16:23:37.443 に答える