【问题标题】:Split string with letters and numbers like C420F140000 [closed]用字母和数字分割字符串,如 C420F140000 [关闭]
【发布时间】:2014-08-08 17:53:57
【问题描述】:

我有一个字符串“F12C429C420T160000000000000000000000000000000000000000000000000000000000000000000000000000" 需要在每个字母上拆分,使其看起来像 F12 C429 C420 T16 并将每个字母放入一个数组中。

此字符串的长度固定为 90,并且可能没有错误代码(全为零)或一个或多个错误代码。

所有代码均以字母开头,后跟 2 到 3 位数字。

10以下的所有数字都以0开头,例如01。

我尝试了一些正则表达式示例,但它们速度较慢。

VB.Net or C# 中有效地进行此提取的任何建议

【问题讨论】:

  • 你好,你试过什么?
  • OP 说他尝试过 Regex,但没有展示出来。好吧。单词。
  • 想要的结果是什么?
  • 你试过new Regex("([A-Z][0-9]{2,3})").Matches("F12C429C420T160000000000000000000000000000000000000000000000000000000000000000000000000000")之类的吗?
  • 顺便说一句:OP 在 cmets 中说,期望的结果是将 T16 作为最后一项。

标签: c# vb.net string split


【解决方案1】:
  • 扫描字符串并计算字母,或以任何其他方式找出数字
  • 预分配一个具有该大小的空字符串数组,所有条目为空
  • 运行一个 for 循环,将扫描从 0 到字符串结尾的索引
  • 在该循环内运行第二个较小的循环,用于检测数字/字母边缘
  • 检测到边缘后,从最后一个字母到边缘创建一个子字符串并将其写入下一个数组条目

这是一个可行的粗略草图。有意排除的变量和细节。这是手动且极简的方法,如果没有并行化,将很难加快速度。您可能还会从使搜索和切割变得懒惰(按需)或本地化(仅从索引...向上搜索...)中受益,但这在很大程度上取决于您系统的其他位。

【讨论】:

  • 字符串只有 90 个字符,所以很难通过 并行化来加快速度。
  • @Gabe - 字符串有 90 个字符,但如果有数百万个字符串,那么并行化可能是合理的。我们再次陷入了 OP 没有提供的内容。
【解决方案2】:

我建议使用正则表达式来解决这个问题。

试试类似的模式

[A-Z][0-9]{2,3}

这将查找带有尾随数字的前导大写字母。

但是,在您的示例中,由于底层字符串,这不是一个完美的解决方案。例如,在您的示例中,最后一个代码可以是 T16T160

如果错误代码列表是有限的,最好创建一个查找表。

如果您正在生成列表,最好使用不同的填充字符来消除上述歧义。

在 cmets 中了解更多细节:

试试

((E|F|T)[0-9]{2}|C[0-9]{3})

这将确保 E/F/T 后跟两位数字,而 c 后跟 3。然后删除上面提到的歧义。因此,您的完整代码可能类似于

Regex expr = new Regex("((E|F|T)[0-9]{2}|C[0-9]{3})");
MatchCollection matches = expr.Matches("F12C429C420T160000000000000000000000000000000000000000000000000000000000000000000000000000");
foreach (Match matchedCode in matches)
{
    Console.WriteLine(matchedCode.Value);
}

【讨论】:

  • +1 表示注意到 T16/T160 歧义
  • 顺便说一句。 OP 刚刚在 cmets 中说过,期望的结果是将 T16 作为最后一项。
  • @quetzalcoatl 感谢您的更新,OP 应该已经澄清了详细信息:)
  • @user3752477 他们还有其他要求吗?
【解决方案3】:

我会为此编写一个方法。您可以简单地循环所有字符并将所有标记放在一个列表中。使用Char.IsDigitChar.IsLetter

Public Shared Function SplitByLetter(text As String) As String()
    Dim list As New List(Of String)
    Dim sb As New System.Text.StringBuilder()

    For Each chr As Char In text
        If Char.IsLetter(chr) Then
            If sb.Length > 0 Then list.Add(sb.ToString())
            sb.Clear()
        End If
        sb.Append(chr)
    Next
    If sb.Length > 0 Then list.Add(sb.ToString())
    Return list.ToArray()
End Function

使用您的示例字符串:

Dim text As String = "F12C429C420T160000000000000000000000000000000000000000000000000000000000000000000000000000"
Dim tokens As String() = SplitByLetter(text)
For Each part As String In tokens
    Console.WriteLine(part)
Next

输出是:

F12
C429
C420
T160000000000000000000000000000000000000000000000000000000000000000000000000000

我不知道最后一个标记是否正确,你没有提到。也许您想在令牌长度超过 3 个字符时停止,然后更改 if

If sb.Length >= 4 OrElse Char.IsLetter(chr) Then

结果是:

F12
C429
C420
T160
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
0000
000

【讨论】:

  • All codes start with a letter followed by 2 to 3 digits.
  • 最后一个 s/b T16。我确实有一个非常基本的工作,但比你的工作要慢,除了 fpr 最后一项,E、F 和 Ts 是字母加 2 位数字,C 是 C 加 3 位数字。
  • @Neolisk:你是对的,它必须是If sb.Length >= 4 而不是> 4,已更正。
  • @user3752447:抱歉,我刚刚注意到您发表了评论。零总是在最后吗?结束错误代码的规则是什么?如果后面至少有两个零,是否达到最后一个错误代码?
【解决方案4】:

我认为这应该可行。我唯一关心的是你怎么知道 T16 和 T160 的区别?

string s = "F12C429C420T160000000000000000000000000000000000000000000000000000000000000000000000000000";
        string result = "";
        foreach (char c in s.TrimEnd('0'))
        {
            if( c > 64)result+=c;
            else result+=' '+c;
        }
        string[] final = result.Split(' ');

【讨论】:

    【解决方案5】:
    class Program
        {    
            static void Main(string[] args)
            {
                List<string> words=new List<string>();                
                string word="";
                string str = "F12C429C420T16000000000000000000000000000000000000
                                         0000000000000000000000000000000000000000";
                foreach (char ch in str)
                {
                    if (char.IsLetter(ch))
                    {
                        words.Add(word);
                        word = ch.ToString();
                    }
                    else
                    {
                        word += ch.ToString();
                    }
                }
                words.Add(word);
                words.RemoveAt(0);
            }
          }
    

    【讨论】:

    • 添加一些解释也无妨。
    猜你喜欢
    • 2021-01-22
    • 2018-09-08
    • 2020-06-30
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    相关资源
    最近更新 更多