Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 拆分多个字符串的最有效方法_C#_Regex_String - Fatal编程技术网

C# 拆分多个字符串的最有效方法

C# 拆分多个字符串的最有效方法,c#,regex,string,C#,Regex,String,我当前的项目处理大量传入的无线消息(每天约500万条),这些消息表示为字符串,然后必须将其划分为预先确定大小的块,以便存储 例如,消息将采用以下格式: mzIIIICCssss (?<m>.)(?<z>.)(?<IIII>.{4})(?<CC>.{2})(?<ssss>.{4}) 每个不同的字符代表一个块,所以这个示例包含5个块(m、z、iii、CC、sss) 使用该格式的消息示例如下: .91234NE0001(,911234,东北

我当前的项目处理大量传入的无线消息(每天约500万条),这些消息表示为字符串,然后必须将其划分为预先确定大小的块,以便存储

例如,消息将采用以下格式:

mzIIIICCssss

(?<m>.)(?<z>.)(?<IIII>.{4})(?<CC>.{2})(?<ssss>.{4})
每个不同的字符代表一个块,所以这个示例包含5个块(m、z、iii、CC、sss)

使用该格式的消息示例如下:

.91234NE0001
(,911234,东北,0001)


到目前为止,我已经使用了
子字符串
,但有人告诉我这不如正则表达式那么有效。如果是这种情况,我如何使用
regex
来匹配字符位置,而不是语义模式?

子字符串
比regex快得多。由于您所要做的只是将字符串分割成固定大小的块,所以只需使用
子字符串


赵的评论给了我另一个想法。您可以使用
字符串(char[],int,int)
构造函数,有点像这样:

string message = ".91234NE0001";
char[] messageArr = message.ToCharArray();
string chunk1 = new string(messageArr, 0, 1);
string chunk2 = new string(messageArr, 1, 1);
string chunk3 = new string(messageArr, 2, 4);
string chunk4 = new string(messageArr, 6, 2);
string chunk5 = new string(messageArr, 8, 4);
您可能可以为变量提供更好的名称:)


这是执行
子字符串
正在执行的操作的手动方式。我原以为它比
子字符串
方法快,但我以前想的方法是错误的。它的速度可能差不多。

忽略哪个解决方案最有效的问题,下面是一个正则表达式,它将匹配问题中给出的格式(
mziiiccssss

(?)(?)(?{4})(?{2})(?{4})
这将捕获名为“m”的组中的一个字符、名为“z”的组中的下一个字符、名为“IIII”的组中的下4个字符、名为“CC”的下2个字符以及名为“ssss”的下4个字符


就性能而言,如果您现在拥有的代码速度不够快,并且您通过分析确定字符串处理是问题所在,那么请寻找更快的替换方法。

我认为在不使用本机代码的情况下,最有效的方法是使用不安全的代码

private static IEnumerable<string> ExtractChunksUnsafe(string format, string data)
{
    if(format.Length != data.Length)
        throw new ArgumentException("Format length must match Data length");

    if(data.Length == 0)
        throw new ArgumentException("Invalid Data length");

    char prevFormat = '\0';
    char currentFormat = format[0];

    var chunks = new List<string>();
    var builder = new StringBuilder();

    unsafe
    {
        fixed(char * indexer = data)
        {
            var index = -1;

            while(data.Length > ++index)
            {
                prevFormat = currentFormat;
                currentFormat = format[index];

                if(currentFormat != prevFormat)
                {
                    chunks.Add(builder.ToString());
                    builder.Clear();
                }

                builder.Append((*(indexer + index)));
            }

            chunks.Add(builder.ToString());
            builder.Clear();
        }
    }

    return chunks;
}
基准:

string format = "mzIIIICCssss";
string data = ".a9876NE9001";

// Warmup CLR
ExtractChunksUnsafe(format, data);
ExtractChunks(format, data);

TimeSpan unsafeCode;
TimeSpan safeCode;

var timer = Stopwatch.StartNew();

for(int i = 0; i < 10000000; i++)
{
    ExtractChunksUnsafe(format, data);
}

unsafeCode = timer.Elapsed;
timer.Restart();

for(int i = 0; i < 10000000; i++)
{
    ExtractChunks(format, data);
}

safeCode = timer.Elapsed;
timer.Stop();


Console.WriteLine("Unsafe time {0}", unsafeCode);
Console.WriteLine("Safe time {0}", safeCode);
甚至修改不安全的身体:

unsafe
{
    fixed(char * indexer = data)
    {
        var prevIndex = 0;
        var index = 1;

        while(data.Length > index)
        {
            prevFormat = currentFormat;
            currentFormat = format[index];

            if(currentFormat != prevFormat)
            {
                chunks.Add(new string(indexer, prevIndex, index - prevIndex));
                prevIndex = index;
            }

            index++;
        }

        chunks.Add(new string(indexer, prevIndex, index - prevIndex));
    }
}

仍然会导致时间变慢
不安全时间00:00:03.4565302

传入消息的格式不清楚。它们是否总是需要分块到完全相同的长度?我不认为正则表达式会比普通的
子字符串
调用快。“被告知”-不要相信谣言,使用基准测试。@RoadieRich是的,消息的大小总是固定的。“提取”是什么意思,期望的结果是什么?展示你的子字符串方法。即使它是真的,也只是一个注释。@TimSchmelter它回答了我所理解的问题。所以使用子字符串时字符串的不可变性不是一个真正的问题?@Lee:Strings的不可变性实际上可以帮上忙——因为字符串不会改变,子字符串可以偏移到主字符串的底层
char[]
。(不确定.net是否能做到这一点;它可能只是Java。)@Lee不是真的,不。对于非常大的字符串,使用正则表达式可能更有效(因为计算复杂),但对于12个字符,使用
子字符串肯定更快。这不是一种。。。杀伤力过大?他说他想要高效。没有什么比直接提取字符更有效的了。@KendallFrey原来
不安全的
代码仍然比安全代码慢。
string format = "mzIIIICCssss";
string data = ".a9876NE9001";

// Warmup CLR
ExtractChunksUnsafe(format, data);
ExtractChunks(format, data);

TimeSpan unsafeCode;
TimeSpan safeCode;

var timer = Stopwatch.StartNew();

for(int i = 0; i < 10000000; i++)
{
    ExtractChunksUnsafe(format, data);
}

unsafeCode = timer.Elapsed;
timer.Restart();

for(int i = 0; i < 10000000; i++)
{
    ExtractChunks(format, data);
}

safeCode = timer.Elapsed;
timer.Stop();


Console.WriteLine("Unsafe time {0}", unsafeCode);
Console.WriteLine("Safe time {0}", safeCode);
Unsafe time 00:00:04.8551136
Safe time 00:00:03.1786573
unsafe
{
    fixed(char * indexer = data)
    {
        var prevIndex = 0;
        var index = 1;

        while(data.Length > index)
        {
            prevFormat = currentFormat;
            currentFormat = format[index];

            if(currentFormat != prevFormat)
            {
                chunks.Add(new string(indexer, prevIndex, index - prevIndex));
                prevIndex = index;
            }

            index++;
        }

        chunks.Add(new string(indexer, prevIndex, index - prevIndex));
    }
}