【问题标题】:How to extract 10 random rows from DataTable?如何从 DataTable 中提取 10 个随机行?
【发布时间】:2011-10-18 02:12:14
【问题描述】:

假设我有一个大约 50 行的 DataTable(SharePoint 中的列表上的 GetDataTable())。我想保留 10 个随机行而忘记其余的。我怎样才能做到这一点?

提前致谢。

【问题讨论】:

    标签: c#


    【解决方案1】:

    您可以对 DataTable 上的行集合使用 Fisher/Yates shuffle(implementation by Skeet),然后选择前 10 个。

    var random10 = dataTable.Rows.OfType<DataRow>().Shuffle(new Random()).Take(10);
    

    【讨论】:

    • 我还要注意,您可以调整 shuffle 以仅执行第一个 n 交换并将它们作为随机集合返回,实际上是通过一次调用进行随机选择.您必须将算法更改为从头到尾排序(或选择最后一个 n 元素)。
    • 您好,这需要什么版本的 .net?我似乎无法将此 Shuffle 方法扩展到 DataRowCollection。
    • @FunkyDude - 它应该适用于从 .NET 3.5 开始的 C# 3.0。
    • 我使用的是 3.5。我是扩展方法的新手,所以我可能做得不对。你能告诉我有什么问题吗? pastebin.com/FAntG1Yu
    • @FunkyDude - 乍一看还不错。有什么问题?你能看不到它还是不能编译?如果您看不到它,可能是因为您在尝试使用它的类中没有包含using CustomExtensions;
    【解决方案2】:

    DataTable 包含属性Rows,即DataRowCollection。您可以使用索引访问这些行中的每一行。

    所以你可以用Random获取随机数,并从myTable.Rows[myRandomIndex]获取数据。

    Random random = new Random();
    int randomNumber = random.Next(0, 50);
    

    【讨论】:

    • 请注意,此方法要求您跟踪已选择的元素,以免重新选择它们。一般来说,这是不可行的,尤其是当您从集合中随机选择大部分元素时。 shuffle 算法通过在 O(N) 中提供随机排序,从减少集合中选择交换以避免重复,然后取前 K 个项目来工作。您可以调整它以仅执行前 K 个交换并返回这些元素以提高性能。
    • 您可以只获取一个随机数并获取行,进行另一个随机数并获取另一行。如果您不想让它们重复,您可以跟踪所采用的索引。这是可行的……
    • 对于少数人来说,是的。但是随着所选行数的增加,您会遇到越来越多的冲突,从而需要更多的选择。事实上,由于选择是随机的,您甚至无法保证最终不会持续选择已经选择的行。实际上,您有概率终止,而不是保证终止,但是元素较少时概率要高得多。参看。 dilbert.com/strips/comic/2001-10-25
    • 这家伙有大约 50 个元素......并且只需要 10 行。使用循环在 0 到 49 之间随机化 10 个唯一数字会产生冲突,但不足以产生任何性能问题。无论如何,没有随机算法会提供 0 碰撞。但是,谢谢您的信息。祝你有美好的一天。
    • Fisher-Yates 通过减少从中选择随机元素的集合来避免冲突,因此它保证是 O(n) 并且是确定性的,而不是概率性的。也就是说,您从整个数组中选择一个随机元素,将其交换到最后一个位置,然后将您考虑的数组元素数量减少一个。最终,您最终得到随机排序的数组,然后选择前 N 个元素。没有冲突,没有重选。 FWIW,我的评论只是它不会扩展并且在一般情况下不可行。对于这种特殊情况,它可能没问题。
    【解决方案3】:

    试试这个:

        Random r = new Random();
        while (dt.Rows.Count > 10)
        {
            int j = r.Next(0, dt.Rows.Count);
            dt.Rows.RemoveAt(j);
        }
    

    【讨论】:

    • 请注意,这是 O(N^2-NK),其中 K 是选择的随机元素的数量,N 是初始数组的大小,因为您必须在删除元素时折叠数组。当 N = 50 时没什么大不了的,但如果你从 1,000,000 中选择 100,那将有很大的不同。 Jon Skeet 的实现遵循的 Fisher-Yates(Durstenfeldt 的版本)是 O(N),对于这个特定问题可以调整为 O(K)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2023-03-28
    相关资源
    最近更新 更多