Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在排序中使用Random会导致[无法对IComparer.Compare进行排序错误]_C#_Linq_List_Sorting_Random - Fatal编程技术网

C# 为什么在排序中使用Random会导致[无法对IComparer.Compare进行排序错误]

C# 为什么在排序中使用Random会导致[无法对IComparer.Compare进行排序错误],c#,linq,list,sorting,random,C#,Linq,List,Sorting,Random,我尝试使用以下任一代码洗牌字节列表(列表): myList.Sort((a, b) => this._Rnd.Next(-1, 1)); 或 他们抛出了以下错误: 无法排序,因为IComparer.Compare()方法返回不一致的结果。一个值与自身比较不相等,或者一个值与另一个值重复比较会产生不同的结果。x:“{0}”,x的类型:“{1}”,IComparer:“{2}” 使用随机函数而不是字节的比较函数有什么错 我试着用LINQ函数来代替它,它很有效 var myNewList =

我尝试使用以下任一代码洗牌字节列表(列表):

myList.Sort((a, b) => this._Rnd.Next(-1, 1));

他们抛出了以下错误:

无法排序,因为IComparer.Compare()方法返回不一致的结果。一个值与自身比较不相等,或者一个值与另一个值重复比较会产生不同的结果。x:“{0}”,x的类型:“{1}”,IComparer:“{2}”

使用随机函数而不是字节的比较函数有什么错

我试着用LINQ函数来代替它,它很有效

var myNewList = myList.OrderBy(s => Guid.NewGuid());
var myNewList = myList.OrderBy(s => this._Rnd.NextDouble());

我确实读到过,这些方法比Fisher慢——Yates shuffle只提供O(n)运行时。但是我只是想知道如何使用Sort函数和random。

因为正如错误所说,random是不一致的。您必须有一个比较器,当给定相同的参数时,它总是返回相同的结果。否则,排序将不一致


Knuth有一个与插入排序类似的随机排序算法,但您将该值与现有数组中随机选择的位置进行了交换。

不仅要求比较关系保持一致,还要求强制执行总排序。例如,你不能说“袜子比鞋子小,衬衫既不比裤子小也不比裤子大”诸如此类的废话,将其输入排序算法,并期望从另一端得到拓扑排序。比较排序之所以称为比较排序,是因为它们需要格式良好的比较关系。特别是,如果比较关系不一致、不可传递、不完全排序,则快速排序可能永远运行,或给出无意义的结果


如果您想要的是一个洗牌,那么实现一个Fischer-Yates洗牌。(正确操作;即使算法很简单,但几乎总是实现错误。)如果您想要的是拓扑排序,那么实现拓扑排序。使用正确的工具进行作业。

排序算法通常通过定义比较函数来工作。算法将重复比较要排序的序列中的两个项目,如果它们的当前顺序与所需顺序不匹配,则交换它们。算法之间的差异主要与在给定情况下找到最有效的方法来进行所有比较有关

在进行所有这些比较的过程中,一个序列中相同的两个元素通常需要进行多次比较!使用非数字数据使这更容易,假设您有值为“Red”和“Apple”的项目。随机比较器在第一次比较时选择“苹果”作为较大的项目。稍后,如果随机比较器选择“红色”作为较大的项,并且这种来回的操作继续进行,则可能会导致算法永远无法完成

大多数情况下,你很幸运,什么也没发生。但有时你不。Net不仅可以永远运行并防止这种情况,而且当这些卫士检测到不一致的排序时,它确实(而且应该!)抛出异常

当然,在一般情况下,正确的处理方法是通过Knuth Fisher-Yates洗牌

更值得一提的是,有时候一个简单的费舍尔·耶茨是不合适的。一个例子是需要将长度未知的序列随机化。。。假设您希望随机重新排列从网络流接收的数据,而不知道流中有多少数据,并尽快将该数据提供给其他位置的工作线程


在这种情况下,你不能完全随机地将这些数据。在不知道流的长度的情况下,您没有足够的信息来正确地执行洗牌,即使您知道了,您可能会发现该长度太长,以至于无法将其全部保存在RAM甚至磁盘上。或者,您可能会发现流在几个小时内无法完成,但您的工作线程需要更快地开始运行。在这种情况下,您可能会满足于(并且理解这是“解决”很重要)一种算法,该算法加载足够长度的缓冲区,随机化缓冲区,将大约一半的缓冲区提供给工作线程,然后重新填充缓冲区的空部分以重复该过程。即使在这里,您也可能使用Knuth-Fisher-Yates对缓冲区进行随机操作。

所以排序函数检查排序函数的一致性?我认为这只是一个伪排序算法,它只跟踪比较器的返回值,不管它返回什么。但我猜如果它在内部使用快速排序,该函数可能已经出现故障,因为它在找到递归的索引时得到了不同的值。排序的目的是产生一致的结果。你用错了!有道理。我想orderby是正确的函数。谢谢
var myNewList = myList.OrderBy(s => Guid.NewGuid());
var myNewList = myList.OrderBy(s => this._Rnd.NextDouble());