【问题标题】:C# Regex.Split: Removing empty resultsC# Regex.Split:删除空结果
【发布时间】:2011-06-22 04:37:49
【问题描述】:

我正在开发一个导入数千行的应用程序,其中每一行的格式如下:

|* 9070183020  |04.02.2011    |107222     |M/S SUNNY MEDICOS                  |GHAZIABAD                          |      32,768.00 |

我正在使用以下Regex 将行拆分为我需要的数据:

Regex lineSplitter = new Regex(@"(?:^\|\*|\|)\s*(.*?)\s+(?=\|)");
string[] columns = lineSplitter.Split(data);

foreach (string c in columns)
    Console.Write("[" + c + "] ");

这给了我以下结果:

[] [9070183020] [] [04.02.2011] [] [107222] [] [M/S SUNNY MEDICOS] [] [GHAZIABAD] [] [32,768.00] [|]

现在我有两个问题。
1.如何删除空结果。我知道我可以使用:

string[] columns = lineSplitter.Split(data).Where(s => !string.IsNullOrEmpty(s)).ToArray();

但是是否有任何内置方法可以删除空结果?

2.如何移除最后一个管道?

谢谢你的帮助。
问候,
尤格什。

编辑:
我想我的问题有点被误解了。这从来都不是关于我怎么能做到的。这只是关于 如何通过更改上述代码中的 Regex 来做到这一点

我知道我可以通过多种方式做到这一点。我已经使用上面提到的带有Where 子句的代码和另一种更快(超过两倍)的方式完成了它:

Regex regex = new Regex(@"(^\|\*\s*)|(\s*\|\s*)");
data = regex.Replace(data, "|");

string[] columns = data.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

其次,作为一个测试用例,我的系统在原始方法中可以在不到 1.5 秒的时间内解析 92k+ 行,在第二种方法中不到 700 毫秒,我永远不会找到超过几千案例,所以我认为我不需要考虑这里的速度。在我看来,在这种情况下考虑速度是过早的优化。

我找到了第一个问题的答案:Split 无法完成,因为没有内置这样的选项。

仍在寻找我第二个问题的答案。

【问题讨论】:

  • 回答你的第一个问题,我相信正则表达式的分组部分应该是@"(.+?)"。否则有可能匹配空白(这就是你现在所拥有的)。
  • 在这种情况下几乎不重要 Jeff。它会给出完全相同的结果。
  • 就像您提到数千个条目的注释一样:使用 String.Split 然后进行更多的字符串处理比首先使用正则表达式要快得多。
  • 您可以通过修改 RegEx 来删除最后一个管道。检查我对进行此类拆分的 RegEx 的回答(尽管您仍然会得到空记录,但是在使用不修剪的拆分时无济于事)。

标签: c# regex split


【解决方案1】:

这个怎么样:

假设我们有一条线:

line1="|* 9070183020  |04.02.2011    |107222     |M/S SUNNY MEDICOS                  |GHAZIABAD                          |      32,768.00 |";

我们可以得到所需的结果:

string[] columns =Regex.Split(line1,"|");
foreach (string c in columns)
         c=c.Replace("*","").Trim();

这将给出以下结果:

[9070183020] [04.02.2011] [107222] [M/S SUNNY MEDICOS] [GHAZIABAD] [32,768.00]

【讨论】:

    【解决方案2】:

    我在这里可能有错误的想法,但您只想使用 '|' 拆分 data 字符串字符作为分隔符?在这种情况下,您可以尝试:

    string[] result = data.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).Select(d => d.Trim()).ToArray();
    

    这将返回所有字段,不包含空格并删除空字段。您可以在Select 部分中随意设置结果的格式,例如

    .Select(d => "[" + d.Trim() + "]").ToArray();
    

    【讨论】:

      【解决方案3】:
      Regex lineSplitter = new Regex(@"[\s*\*]*\|[\s*\*]*");
      var columns = lineSplitter.Split(data).Where(s => s != String.Empty);
      

      或者你可以简单地这样做:

      string[] columns = data.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
      foreach (string c in columns) this.textBox1.Text += "[" + c.Trim(' ', '*') + "] " + "\r\n";
      

      不,没有选项可以像 String.Split 一样删除 RegEx.Split 的空条目。

      你也可以使用火柴。

      【讨论】:

      • +1 回答我的第一个问题。这也是我在 net 和 msdn 文档上看到的内容。
      • 另外,如果你试试我的 RegEx,你会看到除了数组的开头和结尾之外没有空值。
      • 将您的答案标记为选择,因为您最接近。我正在使用我在问题中提到的第二种方法来更快。谢谢。
      • 如果需要忽略空字符串或空白字符串:lineSplitter.Split(data).Where(s => !string.IsNullOrWhiteSpace(s))
      【解决方案4】:

      作为分割的替代方法,当您的分隔符也出现在输入的开头和结尾时,这总是会造成麻烦,您可以尝试匹配管道中的内容:

      foreach (var token in Regex.Matches(input, @"\|\*?\s*(\S[^|]*?)\s*(?=\|)"))
      {
          Console.WriteLine("[{0}]", token.Groups[1].Value);
      }
      
      // Prints the following:
      // [9070183020]
      // [04.02.2011]
      // [107222]
      // [M/S SUNNY MEDICOS]
      // [GHAZIABAD]
      // [32,768.00]
      

      【讨论】:

        【解决方案5】:

        在您的情况下根本不要使用正则表达式。 看起来你不需要一个,而且正则表达式比直接使用字符串函数要慢得多(并且开销要高得多)。

        所以使用有点像:

        const Char[] splitChars = new Char[] {'|'};
        
        string[] splitData = data.Split(splitChars, StringSplitOptions.RemoveEmptyEntries)
        

        【讨论】:

          【解决方案6】:

          我认为这可能相当于删除空字符串:

          string[] splitter = Regex.Split(textvalue,@"\s").Where(s => s != String.Empty).ToArray<string>();
          

          【讨论】:

          • Linq 做得更好的小事的好例子 :)
          【解决方案7】:

          根据@Jaroslav Jandek 的精彩回答,我写了一个extension method,我把它放在这里,也许它可以节省您的时间。

          /// <summary>
          /// String.Split with RemoveEmptyEntries option for clean up empty entries from result
          /// </summary>
          /// <param name="s">Value to parse</param>
          /// <param name="separator">The separator</param>
          /// <param name="index">Hint: pass -1 to get Last item</param>
          /// <param name="wholeResult">Get array of split value</param>
          /// <returns></returns>
          public static object CleanSplit(this string s, char separator, int index, bool wholeResult = false)
          {
              if (string.IsNullOrWhiteSpace(s)) return "";
          
              var split = s.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries);
          
              if (wholeResult) return split;
          
              if (index == -1) return split.Last();
          
              if (split[index] != null) return split[index];
          
              return "";
          }
          

          【讨论】:

            【解决方案8】:

            1.如何删除空结果?

            您可以使用 LINQ 删除所有等于 string.Empty 的条目:

            string[] columns = lineSplitter.Split(data); 
            columns = columns.ToList().RemoveAll(c => c.Equals(string.Empty)).ToArray();
            

            2。如何移除最后一个管道?

            您可以在此处使用 LINQ 删除与您要删除的字符相同的所有条目:

            columns = columns.ToList().RemoveAll(c => c.Equals("|")).ToArray();
            

            【讨论】:

              【解决方案9】:

              使用这个解决方案:

              string stringwithDelemeterNoEmptyValues= string.Join(",", stringwithDelemeterWithEmptyValues.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
              

              【讨论】:

                猜你喜欢
                • 2015-03-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-02-05
                • 1970-01-01
                • 2021-03-29
                • 2018-04-14
                相关资源
                最近更新 更多