8

如果您有此代码:

"......".Split(new String[]{"...", ".."}, StringSplitOptions.None);

结果数组元素是:

 1. ""
 2. ""
 3. ""

现在如果你颠倒分隔符的顺序,

"......".Split(new String[]{"..", "..."}, StringSplitOptions.None);

结果数组元素是:

 1. ""
 2. ""
 3. ""
 4. ""

从这两个示例中,我倾向于得出结论,Split 方法在从左到右遍历数组的每个元素时递归地进行标记。

但是,一旦我们将包含字母数字字符的分隔符放入等式中,很明显上述理论是错误的。

  "5.x.7".Split(new String[]{".x", "x."}, StringSplitOptions.None)

结果是:1. "5" 2. ".7"

   "5.x.7".Split(new String[]{"x.", ".x"}, StringSplitOptions.None)

结果是:1. "5" 2. ".7"

这次我们获得了相同的输出,这意味着基于第一组示例理论化的规则不再适用。(即:如果分隔符的优先级始终根据数组中分隔符的位置确定,那么在最后一个示例中,我们将获得"5."&"7"而不是"5"& ".7"

至于为什么我浪费时间试图猜测 .NET 标准 API 的工作原理,这是因为我想为我的 java 应用程序实现类似的功能,但是 StringTokenizer 和 org.apache.commons.lang.StringUtils 都没有提供拆分一个使用多个多字符分隔符的字符串(即使我要找到确实提供此功能的 API,也很难知道它是否总是使用 String.Split 方法使用的相同算法进行标记。

4

3 回答 3

7

来自MSDN

为避免在分隔符中的字符串具有共同字符时产生模棱两可的结果,Split 操作从实例值的开头到结尾进行,并匹配分隔符中等于实例中分隔符的第一个元素。在实例中遇到子字符串的顺序优先于分隔符中元素的顺序。

因此,对于第一种情况,“..”和“...”位于同一位置,并且它们在分隔符中的顺序用于确定使用的位置。对于第二种情况,“.x”位于“x”之前。并且分隔符中的元素顺序不适用。

于 2013-02-07T23:12:09.693 回答
1

我已经快速查看了这个.. 并且看起来类中的私有方法MakeSeparatorList实际上string检索了一个索引数组.. 但它会匹配它找到的第一个。

因此,因为在您的两个示例中都.x出现在前面,所以x.存储了该索引。

这是我用来测试的代码:

var s = "5.x.7";

string[] separators = new string[] { "x.", ".x" };
int[] sepList = new int[1024];
int[] lengthList = new int[1024];

MethodInfo dynMethod = s.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Last(x => x.Name == "MakeSeparatorList");
dynMethod.Invoke(s, new object[] { separators, sepList, lengthList });

Debugger.Break();

看这个截图:

(我的屏幕截图没有显示?:/)

请注意索引如何为 1(导致.x),即使它.x是数组中的第二个条目。

于 2013-02-07T23:13:02.820 回答
0

string .split 会拆分与参数匹配的第一个匹配字符。在简单的问题中:假设您提供了选项 split("a", "b") 并且字符串包含“appaleisbigapll”,该算法很简单,从第一个字符开始并与 a 或 b 匹配。如果它找到这些,它会分裂并从下一个字符开始。在你的例子中

5.x.7 带有“.x”、“x.”。它使用“或”运算符进行规则,因此它首先找到 .x 并检查剩余的 .7,因为没有剩余的匹配字符,所以它保留 .7 原样。结果 5 和 .7

在第二个问题中也发生了同样的情况,它找到了 .x,正如规则所说的 .x 或 x。它以 .7 继续,此处不应用优先级。对于您的第一组示例,是的,它递归地执行拆分操作。

于 2013-02-07T23:29:11.893 回答