9

我有一组句子需要用来进行替换,例如:

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

我有一个文本可以在哪里进行更改。但是我无法事先知道所述文本的情况。因此,例如,如果我有:

A bgt abc hyi. Abc Ab df h

我必须更换并获得:

A bgt cde nyi. Cde De h

或尽可能接近,即保持大小写

编辑:当我看到对此有很多困惑时,我将尝试澄清一下:

我正在询问一种在更换后保持大写字母的方法,我认为这并没有很好地通过(没有很好地解释 thaat 的含义)所以我将使用真实的单词给出一个更现实的例子。

把它想象成一个八卦,可以说用他们的中义词代替表达,所以如果我映射:

didn't achieve success => failled miserably

然后我得到作为输入的setence:

As he didn't achieve success, he was fired

我会得到

As he failled miserably, he was fired

但是如果没有大写,那么会失败,如果成就或成功被大写,那么悲惨地也会如此

我的主要可能性是(我真正想考虑的可能性)

  • 只有第一个单词的第一个字母大写
  • 只有每个单词的首字母大写
  • 所有字母大写

如果我可以处理这三个我想已经可以接受的问题 - 这是更容易的 - 当然,如果可用,更深入的解决方案会更好

有任何想法吗?

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

编辑 阅读修改后的问题后,这是我修改后的代码(结果与@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.IndexOf with StringComparison.CurrentCultureIgnoreCasespecified 来查找匹配项。那时,一个字符一个字符的替换就可以进行交换了。可以通过检查Char.IsUpper源字符来处理大写,然后根据需要在目标上使用Char.ToUpperChar.ToLower

于 2012-06-19T15:57:02.150 回答
2

您可以将字符串作为字符数组循环并使用Char.IsUpper(char 参数)

  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

一次替换一个字符并使用

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

这几乎就是里德所说的。唯一的技巧是我不确定当FindReplace字符串的长度不同时应该做什么。所以我选择最小长度并使用它......

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 回答