按Random.Next()排序

时间:2010-01-14 00:34:55

标签: .net sorting

this question中,其中一个建议是按Random.Next()排序列表。

我认为(可能不正确)他建议这个

    public static IEnumerable<T> RandomSort<T>(this IEnumerable<T> items)
    {
        Random r = new Random();
        var a = items.ToArray();
        Array.Sort(a, (t1, t2) => (r.Next()%2==0)?-1 : 1);
        return a;
    }

(是的,已经存在一个你明显会使用的Array.RandomShuffle函数。这不是问题)

编辑:海报澄清了答案。他建议使用OrderBy子句

问题是,上面的代码(使用Array.Sort())是否可以安全运行?

我的问题是它将打破排序谓词的基本规律:

如果(a

它甚至不能保证在下次你问的时候(a&lt; b)然后(a&lt; b)。

这会带你进入“未定义的行为”领域吗?

例如,它可能会崩溃或陷入无限循环,具体取决于Random()返回的数字序列?

5 个答案:

答案 0 :(得分:2)

这是用于创建列表的随机排列的有用设备。对于给定的排列,如果ab之前且bc之前,那么ac之前是绝对正确的。< / p>

另一种思考方式是这样的:如果每次使用相同的种子为随机数生成器播种,那么它将始终产生相同的排序。因此,您可以将随机数生成器的每个种子视为生成(可能)列表的不同排序。

  

它甚至不能保证在下次你问的时候(a&lt; b)然后(a&lt; b)。

没关系。但如上所述,如果我们使用相同的种子为随机数生成器播种并将其呈现为Array.Sort,就像在同一状态的示例代码中一样,它将生成相同的顺序。

答案 1 :(得分:1)

只是为了快速观察,因为我刚刚尝试使用以下代码进行这样的随机排序(以便以随机顺序运行一些基本的单元测试):

Action<object>[] tests = new Action<object>[] {
    delegate { SearchStringByTree(SOURCE, distinctor.Keys, out treeResults, out treeTicks); },
    delegate { SearchStringByIndexOf(SOURCE, distinctor.Keys, out indexOfResults, out indexOfTicks); },
    delegate { SearchBinaryByTree(Encoding.UTF8.GetBytes(SOURCE), GetBytes(Encoding.UTF8, TERMS), out utf8Results, out utf8Ticks); },
    delegate { SearchBinaryByTree(Encoding.UTF8.GetBytes(SOURCE), GetBytes(Encoding.ASCII, TERMS), out asciiResults, out asciiTicks); }
};
Random r = new Random();
Array.Sort(tests, delegate { return r.Next(-1, 2); });

我随机获得了以下ArgumentException

IComparer (or the IComparable methods it relies upon) did not return zero 
when Array.Sort called x. CompareTo(x). x: ''  x's type: 'Action`1' 
The IComparer: 'System.Array+FunctorComparer`1[System.Action`1[System.Object]]'.

似乎Sort确实在它知道相同的项上断言相等(假设由object.ReferenceEquals),并且如果Comparer没有为它知道应该相等的那些返回0,则它会使整个排序

答案 2 :(得分:0)

答案 3 :(得分:0)

它的工作方式是它只被问过一次,然后对该值的每个后续查询都是一样的。

就像在表中添加一个额外的列,用随机数填充每个字段,然后按该列排序。

答案 4 :(得分:0)

你是正确的,使用随机数函数进行排序是一种简单的方法来打破通常强加于排序功能的形式要求,包括你提到的那些。

LINQ的当前实现似乎预先计算了所有排序键。以下代码演示了按顺序获取排序键一次。这可能是一个明智的实施,因为它避免了您担心的问题场景。

尽管如此,我不会依赖此行为(MSDN中没有记录Enumerable.OrderBy

    public void Test()
    {
        int[] nums = Enumerable.Range(1, 100).ToArray();
        var sorted = from i in nums orderby Display(i) select i;
        sorted.ToArray();
    }

    private static int Display(int i)
    {
        Console.WriteLine(i);
        return i;
    }

(上面的代码按顺序打印1到100,显示orderby如何评估排序键。)