使用复杂的定界符/分隔符标记字符串并将定界符/分隔符保留为 C# 中的标记的有效方法
Efficient Way to Tokenize String With Complex Delimiter / Separator and Preserving the Delimiter / Separator as Token in C#
我正在尝试找到最有效的方法来创建通用分词器,它将复杂的定界符/分隔符保留为额外的分词。
是的...我查看了一些 SO 问题,例如 How can i use string#split to split a string with the delimiters + - * / ( ) and space and retain them as an extra token?,但到目前为止,它太具体了。我需要针对通用字符串的解决方案。
就我而言,我希望标记化字符串,例如
" A brown bear A red firetruck A white horse "
因此,我期待以下标记:
" ", //3 spaces
"A brown bear",
" ", //5 spaces
"A red firetruck",
" ", //2 spaces
"A white horse",
" " //3 spaces
所以,这是我想出的代码,它按预期工作,但我想知道是否有任何改进...
public static class StringExtension
{
public static List<string> TokenizeUsingRegex(this string input, string separatorRegexPattern, bool includeSeparatorsAsToken = true)
{
var tokens = Regex.Split(input, separatorRegexPattern).Where(t => !string.IsNullOrWhiteSpace(t)).ToList();
if (!includeSeparatorsAsToken)
return tokens;
//Reinstate the removed separators
var newTokens = new List<string>();
var startIndex = 0;
for(int i = 0, l = tokens.Count(); i < l; i++)
{
var token = tokens[i];
var endIndex = input.IndexOf(token);
if (startIndex < endIndex) {
//Add back the separator as a new token
newTokens.Add(input.Substring(startIndex, endIndex - startIndex));
}
//Then add the token afterward
newTokens.Add(token);
startIndex = endIndex + token.Length;
}
//Add last separator if any
if (startIndex < input.Length) {
newTokens.Add(input.Substring(startIndex));
}
return newTokens;
}
}
这个呢?
using System;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
var str = " Invisible Pty. Ltd. 1 Nowhere St. Sydney 2000 AUSTRALIA ";
//str = " A teddy bear A red firetruck ";
//tokenize the input delimited by 2 or more whitespaces
var tokens = Regex.Matches(str, @"\s{2,}|(\s?[^\s]+(\s[^\s]+)*(\s$)?)").Cast<Match>().ToArray();
foreach(var token in tokens)
{
Console.WriteLine("'{0}' - {1}", token, token.Length);
}
}
}
我在 visual studio 中使用了 visual studio 的性能和诊断,这需要 40 毫秒,而现有的需要 80 毫秒。 dotnetfiddle.net 报告性能较慢(?)我可能会更信任 VS,但我只是想把它扔在那里。
基本上它的工作原理是寻找多个 space 或任何其他不超过一个 space 的东西。
我正在尝试找到最有效的方法来创建通用分词器,它将复杂的定界符/分隔符保留为额外的分词。
是的...我查看了一些 SO 问题,例如 How can i use string#split to split a string with the delimiters + - * / ( ) and space and retain them as an extra token?,但到目前为止,它太具体了。我需要针对通用字符串的解决方案。
就我而言,我希望标记化字符串,例如
" A brown bear A red firetruck A white horse "
因此,我期待以下标记:
" ", //3 spaces
"A brown bear",
" ", //5 spaces
"A red firetruck",
" ", //2 spaces
"A white horse",
" " //3 spaces
所以,这是我想出的代码,它按预期工作,但我想知道是否有任何改进...
public static class StringExtension
{
public static List<string> TokenizeUsingRegex(this string input, string separatorRegexPattern, bool includeSeparatorsAsToken = true)
{
var tokens = Regex.Split(input, separatorRegexPattern).Where(t => !string.IsNullOrWhiteSpace(t)).ToList();
if (!includeSeparatorsAsToken)
return tokens;
//Reinstate the removed separators
var newTokens = new List<string>();
var startIndex = 0;
for(int i = 0, l = tokens.Count(); i < l; i++)
{
var token = tokens[i];
var endIndex = input.IndexOf(token);
if (startIndex < endIndex) {
//Add back the separator as a new token
newTokens.Add(input.Substring(startIndex, endIndex - startIndex));
}
//Then add the token afterward
newTokens.Add(token);
startIndex = endIndex + token.Length;
}
//Add last separator if any
if (startIndex < input.Length) {
newTokens.Add(input.Substring(startIndex));
}
return newTokens;
}
}
这个呢?
using System;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
var str = " Invisible Pty. Ltd. 1 Nowhere St. Sydney 2000 AUSTRALIA ";
//str = " A teddy bear A red firetruck ";
//tokenize the input delimited by 2 or more whitespaces
var tokens = Regex.Matches(str, @"\s{2,}|(\s?[^\s]+(\s[^\s]+)*(\s$)?)").Cast<Match>().ToArray();
foreach(var token in tokens)
{
Console.WriteLine("'{0}' - {1}", token, token.Length);
}
}
}
我在 visual studio 中使用了 visual studio 的性能和诊断,这需要 40 毫秒,而现有的需要 80 毫秒。 dotnetfiddle.net 报告性能较慢(?)我可能会更信任 VS,但我只是想把它扔在那里。
基本上它的工作原理是寻找多个 space 或任何其他不超过一个 space 的东西。