【问题标题】:Alphabetical order does not compare from left to right?字母顺序不是从左到右比较吗?
【发布时间】:2014-08-16 00:02:09
【问题描述】:

我认为在 .NET 中,字符串是按字母顺序比较的,并且是从左到右比较的。

string[] strings = { "-1", "1", "1Foo", "-1Foo" };
Array.Sort(strings);
Console.WriteLine(string.Join(",", strings));

我希望这是(或两者都以负号开头):

1,1Foo,-1,-1Foo

但结果是:

1,-1,1Foo,-1Foo

这似乎是一种混合,要么忽略减号,要么比较多个字符,即使第一个字符已经不同。

编辑:我现在测试了OrdinalIgnoreCase,得到了预期的顺序:

Array.Sort(strings, StringComparer.OrdinalIgnoreCase);

但即使我使用InvariantCultureIgnoreCase,我也会得到意外的订单。

【问题讨论】:

  • “-”在字母表中的哪个位置?可能与连字符的单词不要在字典中更改它们的顺序有关
  • 试试这个string.Compare("1", "-1Foo", StringComparison.InvariantCultureIgnoreCase) 和这个string.Compare("-1", "1Foo", StringComparison.InvariantCultureIgnoreCase)。两次都会得到 -1。
  • 他可能使用de-DE文化作为当前的文化。
  • 这不是特定于文化的,这对于 .NET 中的所有文化都是一样的。
  • 你应该使用StringComparer.Ordinal

标签: c# .net string sorting .net-4.0


【解决方案1】:

Jon Skeet 救援here

具体来说:

.NET Framework 使用三种不同的排序方式:单词排序、 字符串排序和序数排序。字排序执行文化敏感 字符串的比较。某些非字母数字字符可能有 分配给他们的特殊权重。例如,连字符 ("-") 可能 分配给它的权重非常小,以便“合作”和“合作” 在排序列表中彼此相邻出现。字符串排序类似于 词排序,除了没有特殊情况。因此,所有 非字母数字符号出现在所有字母数字字符之前。 序数排序根据每个字符串的 Unicode 值比较字符串 字符串的元素。

但是添加 StringComparer.Ordinal 使它的行为如你所愿:

string[] strings = { "-1", "1", "10", "-10", "a", "ba","-a" };      
Array.Sort(strings,StringComparer.Ordinal );
Console.WriteLine(string.Join(",", strings));
// prints: -1,-10,-a,1,10,a,ba

编辑
关于序数,引用自MSDN CompareOptions Enumeration

Ordinal 表示字符串比较必须使用连续 字符串的 Unicode UTF-16 编码值(逐个代码单元的代码单元 比较),导致快速比较,但 文化不敏感。一个以代码单元 XXXX16 开头的字符串来了 如果 XXXX16 小于 YYYY16,则在以 YYYY16 开头的字符串之前。 此值不能与其他 CompareOptions 值组合,并且 必须单独使用。

如果你想要 2 个字符串的序数,你似乎也有 String.CompareOrdinal

这是另一个有趣的注释:

如果可能,应用程序应使用字符串比较方法 接受一个 CompareOptions 值来指定比较类型 预期的。作为一般规则,最好进行面向用户的比较 通过使用语言选项(使用当前文化),而 安全比较应指定 Ordinal 或 OrdinalIgnoreCase。

我猜我们人类在处理字符串时期望序数:)

【讨论】:

  • 谢谢。但是,如果我使用 InvariantCulture 它不应该使用任何文化进行比较。如果我正确理解了您的报价,那应该表示“字符串排序”,它没有像- 这样的特殊情况。这是否意味着如果我不使用Ordinal- 的顺序是任意/不可预测的?
【解决方案2】:

String.CompareTo方法文档上有一个小注:

来电者须知:

字符集包括可忽略的字符。这 CompareTo(String) 方法在执行时不考虑此类字符 执行文化敏感比较。例如,如果以下 代码在.NET Framework 4 或更高版本上运行,比较“动物” 带有“animal”(使用软连字符或 U+00AD)表示这两个 字符串是等价的。

稍后再声明:

要在字符串比较中识别可忽略的字符,请调用 CompareOrdinal(String, String) 方法。

这两个说法似乎和你看到的结果一致。

【讨论】:

  • 但连字符并没有被完全忽略。尝试将"animal""ani-mal" 进行比较,并以两种方式进行比较,您将获得一个在切换值时切换的值,而"1""-1Foo" 然后切换连字符不会。仅此一项不是答案。
  • 另外,即使我使用InvariantCulture,我也会得到相同的结果,但您引用了:“当它执行文化敏感比较时”。顺便说一句,我真的在使用 .NET 4,如果这很重要的话。谢谢
猜你喜欢
  • 2022-01-13
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2013-10-22
相关资源
最近更新 更多