删除空字符串

时间:2009-03-24 15:20:22

标签: c# .net regex

我已经编写了以下正则表达式,并希望自动删除空字符串,并且找不到任何与Regex相同的RemoveEmptyEntries,我只在字符串中找到了Split方法。

string test = "{ key1 = { key2= xx } | key3 = y | key4 = z }";
string[] help = Regex.Split(test, "(=)|({)|(})|(\\|)");

结果字符串数组包含空的元素。我想运行正则表达式而不会产生结果中包含的任何空字符串。

我将非常频繁地运行此代码 - 因此我需要尽可能高效。 更新:由于这是一个解析器,我需要保留令牌,我发现只有一种方法可以让Regex保留它们。

7 个答案:

答案 0 :(得分:4)

我不认为该选项是内置于RegEx中的。但是使用C#3.0,您可以使用简单的.Where()

string[] help = Regex.Split(test, "(=)|({)|(})|(\\|)")
                     .Where(s => !string.IsNullOrEmpty(s)).ToArray();

为了提高效率,请将RegEx声明一次 - 可能在类级别或将其设置为静态 - 而不是一直重新创建它。此外,你只是使用返回的数组来迭代结果。您可以通过跳过最后的.ToArray()调用并保持IEnumerable进行迭代来加快速度。

//earlier
RegEx KeySplitter = new RegEx ("(=)|({)|(})|(\\|)");

//later
string test = ""; // 
for (string key in KeySplitter.Split(test).Where(s => !string.IsNullOrEmpty(s)))
{
    // ...
}

关于linq-to-objects如何工作的一个好处是,它仍然只会迭代.Split结果一次,因为GetEnumerator方法中的Where方法.Select()函数会做懒惰的评估。根据您在for循环中需要执行的操作,您可以通过添加{{1}}调用来获得类似的效率。

答案 1 :(得分:2)

可能不是问题的完整解决方案,但我对手头的问题有一些评论(标记字符串):

the original regex:    (=)|({)|(})|(\|)
is equivalent to:      (=|{|}|\|)
is equivalent to:      ([={}|])

所有上述表达式都返回相同的21个元素,但它们的表现不同。我使用带有Split()RegexOptions.Compiled类的预构建Regex对象,设置了超过100,000次Stopwatch次操作的快速测试。

  • 正则表达式#1在我的硬件上占用2002ms
  • 正则表达式#2需要1691毫秒
  • 正则表达式#3需要1542毫秒
  • 正则表达式#4需要1839毫秒(这是下面的那个)

因人而异。

但是,所需的元素仍然可以被空白区域包围。我认为这也是不受欢迎的,所以我将拆分的正则表达式是:

\s*([={}|])\s*

返回的元素是:

["", "{", "key1", "=", "", "{", "key2", "=", "xx", "}", "", "|", "key3", "=", "y", "|", "key4", "=", "z", "}", ""]

在迭代数组时,少数剩余的空字符串在性能方面不会造成大问题,并且在遇到它们时可以处理(读取:忽略)。

编辑:如果你测量性能,你可能会发现([={}|])上的分裂并且“手动”修剪数组元素比分割\s*([={}|])\s*更快。试试对你有用的东西。

答案 2 :(得分:1)

关于效率:如果明星很幸运,你可以通过编译正则表达式获得一些表现:

Regex r = new Regex ("<regex goes here>", RegexOptions.Compiled);

答案 3 :(得分:1)

要从字符串中删除空格,只需执行此操作

Regex exp = new Regex(@"\s+");
string test = "{ key1 = { key2= xx } | key3 = y | key4 = z }";
string result = test.Replace(exp, string.Empty);

或者您也可以执行以下操作(未测试哪一个更快)

Regex.Replace(test, " ", string.Empty, RegexOptions.Compiled)

以下是Jeff Atwood(顺便提一下StackOverFlow的创建者之一say about compiled regex

在此之后,您可以使用拆分代码将密钥放入字符串数组中。

答案 4 :(得分:0)

我没有弄明白你的问题。但是“^ $”意味着一条线在它开始的地方结束,因此是一条空行。这有帮助吗?

答案 5 :(得分:0)

您可以修改正则表达式并返回匹配集合,而不是使用正则表达式拆分字符串。像这样:

string test = "{ key1 = { key2= xx } | key3 = y | key4 = z }";

Regex regex = new Regex("[={}|]|[^\\s={}|]{1,}");
MatchCollection matches = regex.Matches(test);

string[] help = new string[matches.Count];

for (int index = 0; index < matches.Count; index++)
{
    help[index] = matches[index].Value;                
}

这将返回与正则表达式相同的减去最终数组中的空(空格)元素。

答案 6 :(得分:0)

因此,您希望值之间多次出现的分隔符只能匹配一次。

\s*[{}=|][\s{}=|]*

这应该按此顺序匹配任何数量的空格,一个分隔符,以及任何数量的空白和进一步的分隔符。

添加C#字符串转义和编译声明:

Regex regex = new Regex("\\s*[{}=|][\\s{}=|]*");