【问题标题】:C# - How to select distinct random records from datatableC# - 如何从数据表中选择不同的随机记录
【发布时间】:2016-11-29 21:48:13
【问题描述】:

我正在尝试从 DataTable 随机获取记录,但有一定限制。我可以按如下方式随机获取数据 -

 var r = new Random();
 var _randomSelection = dt.Rows.OfType<DataRow>().OrderBy(rand => r.Next()).Take(limit);

但这些值似乎是多余的。我想获得独特的价值。到目前为止,我已经尝试过 Distinct() 作为 -

var _randomSelection = dt.Rows.OfType<DataRow>().OrderBy(rand => r.Next()).Take(limit).Distinct();

但这似乎没有解决。任何人都可以请指导哪里出了问题。谢谢。

【问题讨论】:

  • 先定义唯一,哪一列指定记录的键?目前Distinct 只能比较不同的DataRow 引用。
  • 您还应该更改顺序,首先使用Distinct(),然后使用Take,否则您通常会获得比请求更少的数据
  • @TimSchmelter 正在获取“id”列的记录。我在 SSMS 中测试了我的查询,它获取了唯一的记录。但似乎与随机函数有关。这就是我得到重复值的原因
  • @Adassko 尝试更改顺序但仍然没有运气:(。值仍然是多余的。
  • 如果dt.Rows 包含唯一记录,您的随机排序永远不会导致重复!您应该更具体地说明您期望的输出和实际得到的输出; 似乎没有解决太模糊了。

标签: c# winforms linq random datatable


【解决方案1】:
   DataTable returnVals = dt.DefaultView.ToTable(true, "ColumnNameOnWhichYouWantDistinctRecords");

ToTable 方法中,第一个参数指定是否需要Distinct 记录,第二个参数指定我们将使用哪个列名来区分。

之后如果你想拿一些,你可以做

var result = returnVals.Rows.Cast<DataRow>().OrderBy(rand => r.Next()).Take(number);

【讨论】:

  • 我在 DataTable 中看不到多余的记录。但是,当我尝试从 DataTable 随机 获取记录时,这似乎导致我的数据重复。
  • 按部分顺序添加到第二行。
  • 在查询本身中使用“DISTINCT”关键字怎么样?只是好奇!
【解决方案2】:

如果您想要根据一列的唯一记录:

var distinctRows = from r in table.AsEnumerable()
                   let id = r.Field<int>("Id")
                   group r by id into idGroup
                   select idGroup.First();

如果您想要根据多列的唯一记录,请使用匿名类型:

var distinctRows = from r in table.AsEnumerable()
                   let keyCols = new { id=  r.Field<int>("Id"), col2 = r.Field<string>("Col2")}
                   group r by keyCols into keyGroup
                   select keyGroup.First();

如果您想要一种动态的方式来比较所有列,即使您不知道它们:

public static class DataTableExtensions
{
    public class DataRowValuesComparer : IEqualityComparer<DataRow>
    {
        public bool Equals(DataRow x, DataRow y)
        {
            if(ReferenceEquals(x, y))
                return true;
            if (x == null || y == null)
                return false;
            if (!ReferenceEquals(x.Table, y.Table))
                return false; // different tables
            foreach (DataColumn column in x.Table.Columns)
            {
                object v1 = x[column];
                object v2 = y[column];
                if (ReferenceEquals(v1, v2)) continue;
                if (v1 == null || v2 == null) return false;
                if (!v1.Equals(v2)) return false;
            }
            return true;
        }

        public int GetHashCode(DataRow obj)
        {
            if (obj == null) return int.MinValue;
            unchecked
            {
                int hash = 19;
                foreach (DataColumn column in obj.Table.Columns)
                {
                    object value = obj[column];
                    hash = hash * 31 + (value?.GetHashCode() ?? 0);
                }
                return hash;
            }
        }
    }

    public static IEnumerable<DataRow> DistinctValues(this IEnumerable<DataRow> rows)
    {
        return rows.Distinct(new DataRowValuesComparer());
    }
}

用法:

var distinctRows = table.AsEnumerable().DistinctValues();

【讨论】:

    猜你喜欢
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多