将文本转换为小写,但对于大写的单词保留大写

本文关键字:于大写 单词 保留 转换 文本 | 更新日期: 2023-09-27 18:10:45

我在c#中寻找一个函数,将字符串转换为小写,但保留原来是大写的单词的大写。

"Pippo, pluto. paperino" -> "pippo, pluto. paperino"
"Pippo, PLUTO. paperino" -> "pippo, PLUTO. paperino"

但如果所有单词都是大写,则转换为小写。

"PIPPO, PLUTO. PAPERINO" -> "pippo, pluto. paperino"

我找到了下面的解决方案。我还考虑了所有的分隔符。你觉得呢?

private static string buildSourceString(string sourceString)
    {
        sourceString += " ";
        var sb = new StringBuilder(sourceString.Length);
        int nOfCharWord = 0;
        int nOfCharLower = 0;
        int nWord = 0;
        int nWordUpper = 0;
        foreach (var c in sourceString)
        {
            if (c == '.' | c == ',' | c == ';' | c == ':' | c == '!' | c == '?' | c == ''n' | c == ''r' || Char.IsWhiteSpace(c))
            {
                if (nOfCharWord > 0)
                    nWord++;
                if (nOfCharWord > 0 && nOfCharWord.Equals(nOfCharLower))
                {
                    for (int i = sb.Length - nOfCharWord; i < sb.Length; i++)
                    {
                        sb[i] = char.ToUpper(sb[i]);
                    }
                    nWordUpper++;
                }
                // reset contatori
                nOfCharWord = 0;
                nOfCharLower = 0;
                sb.Append(c);
            }
            else
            {
                if (c.ToString().Equals(c.ToString().ToUpper()))
                {
                    sb.Append(char.ToLower(c));
                    nOfCharLower++;
                }
                else
                {
                    sb.Append(c);
                }
                nOfCharWord++;
            }
        }
        if (nWord == nWordUpper)
        {
            sb = new StringBuilder(sourceString.Length);
            sb = sb.Append(sourceString.ToLower());
        }
        sb.Remove(sb.Length - 1, 1);
        return sb.ToString();
    }

将文本转换为小写,但对于大写的单词保留大写

public static bool  IsAllUpper(string input)
{
    for (int i = 0; i < input.Length; i++)
    {
        if (Char.IsLetter(input[i]) && !Char.IsUpper(input[i]))
            return false;
    }
    return true;
}
public static string GetString(String input)
{
    var arr = input.Split(' ');
    var result = "";
    foreach(var item in arr)
    {
        if(IsAllUpper(item))
            result += ' ' + item;
        else
            result += ' ' + item.ToLower();

    }
    return result;
}
public static void Main()
{
    String s1 = "Pippo, pluto. paperino";
    String s2 = "Pippo, PLUTO. paperino";
    String s3 = "PIPPO, PLUTO. PAPERINO";

    Console.WriteLine(GetString(s1));
    Console.WriteLine(GetString(s2));
    Console.WriteLine(GetString(s3));

}

这将把句子开头的任何小写单词转换为大写单词。例如:

嗨。我是Matteo,在IP工作。

将被转换为

嗨。我是Matteo,在IP工作。

相似的,

嗨。我是Matteo,在IP工作。请把你的问题直接问我。请随时给我发邮件或打电话。

将转换为:

嗨。我是Matteo,在IP工作。请把你的问题直接问我。请随时给我发邮件或打电话。

在您的问题中处理这种特定字符串操作的最佳方法是使用Regex类。我建议看看MSDN关于如何在。net中使用正则表达式的最小文档。如果你不熟悉如何使用正则表达式,你可以通过你喜欢的搜索引擎找到很多帮助。

我将用最后一个例子来说明。为了与MSDN提供的示例相吻合(说明Replace()过载):
class Program
{
    static void Main(string[] args)
    {
        string original = "hi. i'm Matteo and work in IP";
        Console.WriteLine(Regex.Replace(original, @"'A[a-z]|(?<='W{2})[a-z]", new MatchEvaluator(CapText), RegexOptions.ECMAScript));
        Console.ReadKey();
    }
    static string CapText(Match match)
    {
        string tempStr = match.ToString();
        if (char.IsLower(tempStr[0]))
        {
            return char.ToUpper(tempStr[0]) + tempStr.Substring(1, tempStr.Length - 1);
        }
        return tempStr;
    }
}

两个关键部分是Regex.Replace中的正则表达式和CapText中的自定义求值器方法。

Regex.Replace中的正则表达式可以分解为:

  • 'A[A -z]查找字符串开头的小写字母A到z。
  • |是交替/或操作数,所以在它之前或之后的逻辑都适用。
  • (?<='W{2})是正向向后查找,它在以下集合之前搜索恰好两个非单词字符…
  • …这是最后一个[a-z],它搜索小写字母a到z。

我爱TDD:-)使用你的参数我到达这个类:

internal static class ToLowerEx
{
    static readonly Regex Words = new Regex(@"(?'item''b'w+'b)|(?'item''b'W+'b)", RegexOptions.ExplicitCapture);
    public static string Get(string text)
    {
        if (!Words.IsMatch(text)) return text;
        var result = new StringBuilder();
        var matches = Words.Matches(text);
        foreach (Match match in matches)
            result.Append(ProcessWord(match.Value));
        return result.ToString();
    }
    private static string ProcessWord(string text)
    {
        return !text.All(char.IsUpper)
            ? text.ToLower()
            : text;
    }
}

如果你感兴趣的话,这些是测试:

[TestFixture]
internal class LowerTests
{
    [Test]
    public void Test_asdf_asdf()
    {
        var actual = ToLowerEx.Get("asdf");
        const string expected = "asdf";
        Assert.AreEqual(expected, actual);
    }
    [Test]
    public void Test_Asdf_asdf()
    {
        var actual = ToLowerEx.Get("Asdf");
        const string expected = "asdf";
        Assert.AreEqual(expected, actual);
    }
    [Test]
    public void Test_aSdf_asdf()
    {
        var actual = ToLowerEx.Get("aSdf");
        const string expected = "asdf";
        Assert.AreEqual(expected, actual);
    }
    [Test]
    public void Test_ASDF_ASDF()
    {
        var actual = ToLowerEx.Get("ASDF");
        const string expected = "ASDF";
        Assert.AreEqual(expected, actual);
    }
    [Test]
    public void Test_asdfAndqwer_asdfAandqwer()
    {
        var actual = ToLowerEx.Get("asdf, qwer");
        const string expected = "asdf, qwer";
        Assert.AreEqual(expected, actual);
    }
    [Test]
    public void Test_AsdfAndqWer_asdfAandqwer()
    {
        var actual = ToLowerEx.Get("Asdf, qWer");
        const string expected = "asdf, qwer";
        Assert.AreEqual(expected, actual);
    }
    [Test]
    public void Test_AsdfAndQWER_asdfAandQWER()
    {
        var actual = ToLowerEx.Get("Asdf, QWER");
        const string expected = "asdf, QWER";
        Assert.AreEqual(expected, actual);
    }
}

遵循下面的代码

private void button1_Click(object sender, EventArgs e)
{
    String s1 = "Pippo, pluto. paperino";
    String s2 = "Pippo, PLUTO. paperino";
    String s3 = "PIPPO, PLUTO. PAPERINO";
    MessageBox.Show(myStringConverter(s1));
    MessageBox.Show(myStringConverter(s2));
    MessageBox.Show(myStringConverter(s3));
}

public string myStringConverter(string str)
{
    string[] strArray = str.Split(' '); // Word is always seprate by Space.
    string Answer = "";
    for (int i = 0; i < strArray.Length; i++)
    {
        string tempStr = strArray[i];
        var withoutSpecialCharacter = new string(tempStr.Where(c => Char.IsLetterOrDigit(c) || Char.IsWhiteSpace(c)).ToArray());
        if (!withoutSpecialCharacter.All(char.IsUpper))
        {
            Answer += strArray[i].ToLower() + " ";
        }
        else
        {
            Answer += strArray[i] + " ";
        }
    }
    return Answer;
}