【问题标题】:How to split string with longer separators being preferred over shorter ones?如何拆分字符串,较长的分隔符优于较短的分隔符?
【发布时间】:2019-06-10 13:33:34
【问题描述】:

我有一个string,我想将它一分为二。通常它是一个名称、运算符和一个值。我想将其拆分为名称和值。名称可以是任何东西,值也可以。我所拥有的是一组运算符,我的想法是将其用作分隔符:

var input = "name>=2";
var separators = new string[]
{
    ">",
    ">=",
};
var result = input.Split(separators, StringSplitOptions.RemoveEmptyEntries);

上面的代码给出的结果是name=2。但是如果我重新排列分隔符的顺序,那么>= 将是第一个,如下所示:

var separators = new string[]
{
    ">=",
    ">",
};

这样,我的name2 越来越好,这就是我想要实现的目标。可悲的是,让分隔符保持完美的顺序对我来说是不行的。此外,我收集的分隔符也不是一成不变的。所以,我在想也许我可以用较长的分隔符分割string,并优先考虑较短的分隔符?

感谢您的帮助!

Here 是一个相关问题,解释了为什么在Split() 方法中会出现这种行为。

【问题讨论】:

  • var result = Regex.Split(input, "[><=]+"); - 我们根据<>= 的任意组合进行拆分,例如name>>4name===otherinput<>-456name<=5name>=7
  • var result = input.Split(separators.OrderByDescending(s => s.Length).ToArray(), StringSplitOptions.RemoveEmptyEntries); - 我们以正确的方式排序分隔符,然后在其中一些分隔符上进行拆分

标签: c# string split


【解决方案1】:

您可以尝试多种选择。如果您有分隔符的集合,您可以在拆分前按正确的顺序对它们进行排序:

  using System.Linq;

  ...

  var result = input.Split(
    separators.OrderByDescending(item => item.Length), // longest first
    StringSplitOptions.RemoveEmptyEntries);

您可以尝试将所有(包括可能的)分隔符组织成一个模式,例如

 [><=]+

这里我们按照&gt;&lt;=最长序列进行分割

 var result = Regex.Split(input, "[><=]+");

演示:

  using System.Text.RegularExpressions;

  ...

  string[] tests = new string[] {
    "name>123",
    "name<4",
    "name=78",
    "name==other",
    "name===other",
    "name<>78",
    "name<<=4",
    "name=>name + 455",
    "name>=456",
    "a_b_c=d_e_f",
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => string.Join("; ", Regex.Split(test, "[><=]+"))));

  Console.Write(report);

结果:

name; 123
name; 4
name; 78
name; other
name; other
name; 78
name; 4
name; name + 455
name; 456
a_b_c; d_e_f

【讨论】:

  • 感谢您的回答@Dmitry。对运算符进行排序似乎是个好主意。尽管如此,在您的第二个解决方案中,我注意到一个重大缺陷。如果名称包含下划线之类的符号,例如first_name 和 separators 集合将包含任何使用下划线的分隔符,例如_=,然后first_name 也将拆分为firstname,这不是我想要的结果。
  • @Prolog:是的,通常情况下,当将所有分隔符组织成一个模式时,我们不能只是机械地将它们粘合在一起。对于_= 分隔符,我们要添加_=,我们可以尝试,例如_?[&gt;&lt;=]+ 模式:最多一个_,后跟至少一个&gt;、'= 符号。所以_= 是一个分隔符,当_ - 不是
【解决方案2】:

您可以尝试在交替列出较长的&gt;= 时进行正则表达式拆分:

var input = "name>=2";
string[] parts = Regex.Split(input, "(?:>=|>)");
foreach(var item in res)
{
    Console.WriteLine(item.ToString());
}

打印出来:

name
2

请注意,如果我们在 (?:&gt;|&gt;=) 上拆分,输出将是 name=2

【讨论】:

  • 可能值得指出的是,OP 可以使用他们的 separators 数组和一些 OrderByDescendingString.Join 操作来生成这种模式。
  • @Jamiec 我希望我知道更多 C#,在这种情况下我也可以提供这些选项:-)
  • var pattern = "(?:" + String.Join("|",separators.OrderByDescending(s =&gt; s.Length)) + ")"(例如:rextester.com/INYGH99691
  • 感谢您的回答@Tim 和 jamiec 的宝贵意见。我可以访问操作符集合,但我不能 100% 确定操作符的外观,因为我允许在自定义中添加操作符。因此,我会使用正则表达式作为绝对确定性。运营商集合可以扩展,所以我更喜欢未来的证明和风险更低的解决方案。也许我应该写更多关于操作符集合不是不可变的原因,对此感到抱歉。无论如何,再次感谢您的回答,我确信有类似问题的人会在这里找到解决方案,感谢您。
猜你喜欢
  • 1970-01-01
  • 2019-05-08
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 2011-11-28
  • 2012-11-07
相关资源
最近更新 更多