识别字符串中的字符/数字/特殊字符数

时间:2017-03-07 06:05:19

标签: c# string

我想根据C#中的字母数字,数字和特殊字符来计算字符串的摘要。例如:

  

字符串 abc123 $%应该包含 A3D3S2 等摘要(表示3个字母,3个数字和2个特殊字符)

     

a34 = $ @ 应该包含 A1D2S3 等摘要(表示1个字母,2个数字和3个特殊字符)

     

a3b $ s 应该有 A1D1A1S1A1 (这意味着1个字母,1个数字,1个字母,1个特殊字符,1个字母)的摘要

任何人都可以指导我如何编写能够快速执行上述任务的算法?我认为如果我按字符搜索字符串,则需要相当长的时间。我有一个庞大的字符串数据集。

5 个答案:

答案 0 :(得分:3)

这有效:

    static string GetSummary(string input)
    {
        var sb = new StringBuilder();

        string prevMode = "";
        string curMode = "";
        int sameModeCount = 0;

        for (int i = 0; i <= input.Length; ++i)
        {
            if (i < input.Length)
            {
                char c = input[i];
                if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')
                {
                    curMode = "A";
                }
                else if ('0' <= c && c <= '9')
                {
                    curMode = "D";
                }
                else
                {
                    curMode = "S";
                }
            }
            else
            {
                curMode = "";
            }

            if (curMode != prevMode && prevMode != "")
            {
                sb.Append(prevMode);
                sb.Append(sameModeCount);

                sameModeCount = 0;
            }

            prevMode = curMode;
            ++sameModeCount;
        }

        return sb.ToString();
    }

测试:

    public static void Main()
    {
        Console.WriteLine(GetSummary("abc123$%"));
        Console.WriteLine(GetSummary("a34=$@"));
        Console.WriteLine(GetSummary("a3b$s"));
    }

结果:

A3D3S2
A1D2S3
A1D1A1S1A1

答案 1 :(得分:2)

使用FOR循环浏览每个字符。如果角色在a-zA-Z范围内,那么它就是一个字母。如果在0-9的范围内,则它是一个数字的其他特殊字符。

<强>代码

string inputStr = "a3b$s";
string outputStr = string.Empty;
char firstChar = Convert.ToChar(inputStr.Substring(0, 1));
outputStr = char.IsLetter(firstChar) ? "A1" : char.IsDigit(firstChar) ? "D1" : "S1";
for (int i = 1; i < inputStr.Length; i++)
{
    char nextChar = char.IsLetter(inputStr[i]) ? 'A' : 
                       char.IsDigit(inputStr[i]) ? 'D' : 'S';
    char prevChar = Convert.ToChar(outputStr.Substring(outputStr.Length - 2, 1));
    if (nextChar == prevChar)
    {
        int lastDig = Convert.ToInt32(outputStr.Substring(outputStr.Length - 1, 1));
        outputStr = outputStr.Substring(0, outputStr.Length - 1) + 
                         (lastDig + 1).ToString();
    }
    else
        outputStr += nextChar.ToString() + "1";
}
Console.WriteLine(outputStr.ToString());

<强>输出

A1D1A1S1A1

<强> Find demo here

答案 2 :(得分:2)

使用Linq,你可以这样做:

string myinput = "abc123$%";
            int letter =0 , digit = 0, specialCharacter = 0;
            myinput.ToCharArray().ToList().ForEach(x =>
            {
                letter = Char.IsLetter(x) ? ++letter : letter;
                digit = Char.IsDigit(x) ? ++digit : digit;
                specialCharacter = !Char.IsLetterOrDigit(x) ? 
                                  ++specialCharacter : specialCharacter;
            });
            string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit, 
                                                       specialCharacter);

您可以直接在Linq ForEach中使用数组,而无需通过以下方式转换为列表:

Array.ForEach(myinput.ToCharArray(), x =>
            {
                letter = Char.IsLetter(x) ? ++letter : letter;
                digit = Char.IsDigit(x) ? ++digit : digit;
                specialCharacter = !Char.IsLetterOrDigit(x) ? ++specialCharacter : specialCharacter;
            });
            string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit, specialCharacter);

答案 3 :(得分:2)

这应该有效:

    string s = "a3b$s";
    char etype = 'X'; //current character's type
    char etypeinit = 'X'; //tracker variable - holds type of last character
    string str = "";
    int count = 1;
    foreach(char c in s)
    {
        //Use this block of conditionals to assign type for current character
        if(char.IsLetter(c))
        {
            etype = 'A';
        }
        else if(char.IsDigit(c))
        {
            etype = 'D';
        }
        else
        {
            etype = 'S';
        }

        //This is a different type of character compared to the previous one
        if(etypeinit != etype)
        {
            str += string.Format("{0}{1}",etype,count); //Build the string
            count = 1; //Reset count
        }
        else
        {
            count++; //Increment because this is the same type as previous one
        }
        etypeinit = etype; //Set tracker variable to type of current character

    }

    Console.WriteLine(str);

答案 4 :(得分:2)

稍微复杂一点,但能够根据问题中的给定输入产生所有预期输出,请看一下:

string inputString = "abc123$%ab12";

var results = inputString.Select(x => char.IsLetter(x) ? 'A' :
                                     char.IsDigit(x) ? 'D' : 'S');
StringBuilder outPutBuilder = new StringBuilder();
char previousChar = results.First();
int charCount = 0;
foreach (var item in results)
{
    switch (item)
    {
        case 'A':
            if (previousChar == 'A')
            {
                charCount++;
            }
            else
            {
                outPutBuilder.Append(previousChar.ToString() + charCount);
                charCount = 1;
            }
            break;
        case 'D':
            if (previousChar == 'D')               
                charCount++;               
            else
            {
                outPutBuilder.Append(previousChar.ToString() + charCount);
                charCount = 1;
            }
            break;
        default:
            if (previousChar == 'S')
               charCount++;               
            else
            {
                outPutBuilder.Append(previousChar.ToString() + charCount);
                charCount = 1;
            }
            break;
    }
    previousChar = item;
}
outPutBuilder.Append(previousChar.ToString() + charCount);

Working example