为什么默认字符串比较器无法保持传递一致性?

2024-03-31

我知道这个问题之前已经注意到 https://stackoverflow.com/questions/9354966/string-sorting-issue-in-c-sharp/9355086#9355086,或多或少简洁,但我仍然创建这个新线程,因为我在编写单元测试时再次遇到了这个问题。

默认字符串比较(即我们使用的依赖于区域性的区分大小写的比较string.CompareTo(string), Comparer<string>.Default, StringComparer.CurrentCulture, string.Compare(string, string)当字符串包含连字符(或减号,我说的是普通的 U+002D 字符)时,它会违反传递性。

这是一个简单的重现:

static void Main()
{
  const string a = "fk-";
  const string b = "-fk";
  const string c = "Fk";

  Console.WriteLine(a.CompareTo(b));  // "-1"
  Console.WriteLine(b.CompareTo(c));  // "-1"
  Console.WriteLine(a.CompareTo(c));  // "1"

  var listX = new List<string> { a, b, c, };
  var listY = new List<string> { c, a, b, };
  var listZ = new List<string> { b, c, a, };
  listX.Sort();
  listY.Sort();
  listZ.Sort();
  Console.WriteLine(listX.SequenceEqual(listY));  // "False"
  Console.WriteLine(listY.SequenceEqual(listZ));  // "False"
  Console.WriteLine(listX.SequenceEqual(listZ));  // "False"
}

在上半部分我们看到传递性是如何失败的。a小于b, and b小于c, yet a未能小于c.

这违背了记录的行为 http://www.unicode.org/faq/collation.html#5Unicode 排序规则指出:

...对于任何字符串 A、B 和 C,如果 A

现在对列表进行排序a, b and c就像试图对双手进行排名一样“石头”、“布”、“剪刀” http://en.wikipedia.org/wiki/Rock-paper-scissors在著名的不及物游戏中。这是一项不可能完成的任务。

上面代码示例的最后一部分显示排序结果取决于元素的初始顺序(并且列表中没有两个元素比较“相等”(0)).

Linq's listX.OrderBy(x => x)当然也受到影响。这应该是一个稳定的排序,但是当排序包含以下内容的集合时,您会得到奇怪的结果a, b and c与其他字符串一起。

我尝试过这个all the CultureInfo在我的机器上(因为这是一种依赖于文化的类型),包括“不变的文化”,并且每个人都有相同的问题。我在 .NET 4.5.1 运行时尝试过此操作,但我相信旧版本也有相同的错误。

结论:当使用默认比较器对 .NET 中的字符串进行排序时,如果某些字符串包含连字符,则结果是不可预测的。

.NET 4.0 中引入了哪些更改导致了此行为?

据观察,这种行为在不同版本的平台上是不一致的:在 .NET 3.5 中,带有连字符的字符串可以可靠地排序。在框架的所有版本中,调用System.Globalization.CultureInfo.CurrentCulture.CompareInfo.GetSortKey提供独特的DeyData对于这些字符串,为什么它们没有正确排序呢?


Microsoft Connect 讨论 https://connect.microsoft.com/VisualStudio/feedback/details/785931/string-compare-with-accents-on-framework-4-5-windows-8这是一些解决方法的代码:

static int CompareStringUsingSortKey(string s1, string s2)
{
    SortKey sk1 = CultureInfo.InvariantCulture.CompareInfo.GetSortKey(s1);
    SortKey sk2 = CultureInfo.InvariantCulture.CompareInfo.GetSortKey(s2);
    return SortKey.Compare(sk1, sk2);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么默认字符串比较器无法保持传递一致性? 的相关文章

  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 字符串数组文本格式化

    我有这个字符串 String text Address 1 Street nr 45 Address 2 Street nr 67 Address 3 Street nr 56 n Phone number 000000000 稍后将被使用
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 重载<<的返回值

    include
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 使用日期 Swift 3 对字典数组进行排序

    我有一个名为 myArray 的数组 其中添加了字典 我希望该字典按时间排序 这是字典中的键 那个时间是在 String 中 时间的日期格式为 yyyy MM dd HH mm ss 我尝试使用下面的代码解决方案 但给出了 从 字符串转换
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 从 Reddit 评论中删除链接

    我正在阅读 reddit 帖子下的评论 有些评论带有链接 我想删除它们 示例 输入 This is a pic https i imgur com yKmUMJD jpg this http www google com is a link
  • 去审查:“复合文字使用无键字段”和嵌入类型

    我有一个简单的结构 type MyWriter struct io Writer 然后我按以下方式使用它 writer MyWriter io Stdout 跑步时go vet这给了我一个composite literal uses unk
  • Laravel 组管理路由

    有没有一种方法可以将所有以admin 我尝试过这样的事情 但它当然不起作用 Route group admin function Route get something array uses gt mycontroller index Ro
  • Android HTTP 调用的随机异常。为什么?

    到目前为止 我正在 3 台设备上测试我的应用程序 Sprint 的 LG Optimus 设备在 https 调用上不会抛出异常 可能一周一次 T Mobile 上的 Nexus S 几乎每小时都会出现这样的内容 读取错误 ssl 0x3f
  • 如何使用 React Native 检测屏幕解锁?

    有谁知道我可以检测用户何时打开手机的方法吗 据我了解 当设备解锁时 例如输入正确的密码 android intent USER PRESENT 会被广播 但是 我不知道如何使用 React Native 来检测广播 有没有人有办法解决吗 调
  • 增加Python中cProfiler的深度以报告更多功能?

    我正在尝试分析一个调用其他函数的函数 我按如下方式调用分析器 from mymodule import foo def start foo import cProfile as profile profile run start outpu
  • 使用着色器创建模糊过滤器 - 从片段着色器访问相邻像素?

    我想使用 OpenGL ES 2 0 中的片段着色器创建模糊效果 我感兴趣的算法只是一个平均模糊 将所有相邻像素添加到我自己中并除以 9 进行标准化 但是我有两个问题 1 这是否需要我首先渲染到帧缓冲区 然后切换渲染目标 或者有更简单的方法
  • 在 Java 中过滤组合框数据

    在java中 假设有两个jpanel 当我单击Panle 1 上的按钮 A 时 它将显示面板 2 在面板 2 中 有两个组合框 我完成了所有必要的编码 但要过滤的一件事是组合框 1 将仅显示那些具有 book 前缀的数据 组合框 2 将仅显
  • Hibernate 对象相等性检查[重复]

    这个问题在这里已经有答案了 可能的重复 Hibernate 具有相同标识符值的不同对象已与会话关联 https stackoverflow com questions 3553200 hibernate different object w
  • 如何管理 Workflow Foundation 中的版本?

    当您有长时间运行的工作流并且持久性存储中可能同时有两个或三个版本并且必须能够访问所有版本时 如何管理 WF 中的工作流版本 我撰写了一系列 4 篇博客文章 涵盖了对长期运行的工作流程进行版本控制时需要注意的大部分内容 我倾向于避免的一件事是
  • 在设备上打印视图层次结构

    在我无法实际访问的三星手机上调试我的应用程序 结果出现奇怪的结果 我想要求用户运行一个已检测的应用程序来帮助调试 我的应用程序获得view其中有一个未知的 对我来说 层次结构 ViewGroupsETC 有没有办法 走路 View并打印出一
  • sencha列表分页插件

    我正在尝试使用 sencha touch 的列表分页插件 但几乎没有关于如何使用它的好 或坏 文档 我很困惑 当我激活列表中的插件时 this myList new Ext List store this myStore plugins p
  • 在 vim 中反转逗号分隔列表的最快方法是什么?

    我经常必须更正以下 Rails 代码 assert equal value expected assert equal 的两个参数是乱序的 应该是 assert equal expected value 在vim中 从第一行到第二行最有效的
  • 如何使用 C++ 初始化 const char 数组数据成员?

    我有一个与 C 类成员初始化相关的问题 下面的代码说明了我的问题 class ABCD public ABCD ObjNum 3 ABCD static const unsigned char getByte 8 const int Obj
  • 获取不包含滚动条宽度的 Div 宽度

    我这里有个问题 这里有两个div div1 和 div2 这里我想根据 div2 宽度调整 div1 宽度 我的要求是 div1 不应包含滚动条的宽度 即我应该设置 div1 的高度 不包括 div2 中滚动条的宽度 我想要一个 jquer
  • 如何将目录中每个文件中的制表符转换为空格?

    如何将目录中每个文件中的制表符转换为空格 可能递归地 另外 有没有办法设置每个选项卡的空格数 简单替换为sed可以 但不是最好的解决方案 如果选项卡之间存在 额外 空格 则它们在替换后仍将存在 因此边距将参差不齐 在行中间展开的选项卡也将无
  • 什么是方法内联? [复制]

    这个问题在这里已经有答案了 我一直试图理解这真正意味着什么 内联函数 在 C 中 定义的成员函数 类声明 2 函数 调用编译器替换为 该函数的实际代码 这 关键字 inline 可用于提示 编译器执行内联 成员身体的扩张或 非成员函数 in
  • 我可以在为 kindle fire 商店发布的应用程序中使用 Google Analytics 吗?

    我目前在 Play 商店中有一个使用谷歌分析的应用程序 我想修改并发布该应用程序到 Kindle 应用程序商店 并且仍然能够使用 GA 据我了解 这取决于播放服务能否正常工作 显然 kindle 设备上没有播放服务 但有没有办法将它们包含在
  • 将 ZeroMQ 交叉编译为 ARM,以便在 MonoTouch iPhone 应用程序配置设置中使用

    我正在尝试在使用 MonoTouch 用 C 开发的 iPhone 应用程序中使用 ZeroMQ 库 我几乎解决了所有的问题 却在最后一道坎倒下了 我正在使用 ZeroMQ 2 1 10 和 C CLR 绑定 包装器 并在 Mac OS X
  • 为什么默认字符串比较器无法保持传递一致性?

    我知道这个问题之前已经注意到 https stackoverflow com questions 9354966 string sorting issue in c sharp 9355086 9355086 或多或少简洁 但我仍然创建这个