c# - 从具有动态列的数据表中选择不同的行

标签 c# linq datatable

我需要对 DataTable 运行 LINQ 查询以使用多个列获取不同的值。如果我事先知道我需要选择的列,我可以使用来自 David Hoarser 的答案 Select distinct rows from datatable in Linq :

var distinctValues = dsValues.AsEnumerable()
                    .Select(row => new {
                        attribute1_name = row.Field<string>("attribute1_name"),
                        attribute2_name = row.Field<string>("attribute2_name")
                     })
                    .Distinct();

但是,在我的例子中,我有需要在对象列表中选择的列名:

public class PC{
    public string Name{get;set;} 
    public string NumFormat{get;set}
}
List<PC>cols=new List<PC>();
cols.AddRange(new PC[]{new PC{Name="FullName",NumFormat=""},
                      {new PC{Name="Salary",NumFormat="$ #,##0"}});

我可以使用上面 David 的示例来构建 select 语句:

var distinctValues = dsValues.AsEnumerable()
                .Select(row => new {
                    attribute1_name = row.Field<string>(cols[0].Name),
                    attribute2_name = row.Field<string>(cols[1].Name)
                 })
                .Distinct();

但这行不通,因为我不知道我需要选择多少列,因为 cols 列表可能会有所不同。我如何遍历列列表来构建我的 Select 语句以最终获得我的 Distinct 值?

最佳答案

您可以为该任务实现自定义 IEqualityComparer

class DataRowComparer : IEqualityComparer<DataRow>
{
    private readonly List<string> _columns = new List<string>();
    public DataRowComparer(DataColumnCollection cols)
    {
        foreach (DataColumn col in cols)
        {
            _columns.Add(col.ColumnName);
        }
    }

    public bool Equals(DataRow x, DataRow y)
    {
        foreach (var column in _columns)
        {
            if (!IsEqual(x, y, column))
                return false;
        }

        return true;
    }


    public int GetHashCode(DataRow obj)
    {
        unchecked
        {
            var hash = 19;
            foreach (var column in _columns)
            {
                hash = hash*31 + (obj[column] == null ? 0 : obj[column].GetHashCode());
            }

            return hash;
        }
    }

    private static bool IsEqual(DataRow x, DataRow y, string column)
    {
        if (x[column] == null && y[column] == null)
            return true;

        if (x[column] == null || y[column] == null)
            return false;

        return x[column].Equals(y[column]);
    }
}

用法

var distinctValues = dsValues
                 .AsEnumerable()
                 .Distinct(new DataRowComparer(dsValues.Columns))
                 .ToList();

您还可以为DataTable 创建扩展方法

static class DataTableExtension
{
    public static IEnumerable<DataRow> DistinctRow(this DataTable table)
    {
        return table
            .AsEnumerable()
            .Distinct(new DataRowComparer(table.Columns));
    }
}

用法

var distinctValues = dsValues
                    .DistinctRow()
                    .ToList();

关于c# - 从具有动态列的数据表中选择不同的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40307577/

相关文章:

c# - Windows 窗体启动时出现尴尬的 "Resizes"

linq - 学习 LinqToSql 还是坚持使用 ADO.NET?

c# - 将字典列表转换为模型

javascript - 从数据表中删除垂直边界线

c# - 在特定文件夹上创建一个包含今天日期的新文件夹

c# winform cool colordialog 收藏

flutter - 在flutter中动态显示数据表布局中的JSON数据

c# - 数据表和 AutoGeneratedColummns 中带有枚举的 WPF DataGrid ="True"

c# - LINQ 列表到句子格式(插入逗号和 "and")

C# 按字母顺序排序 a - z,然后排序为 aa、ab - zz