从带有动态列的数据表中选择Distinct Row

时间:2016-10-28 14:43:58

标签: c# linq datatable

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

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();

但由于我不知道有多少列需要选择Distinct,因为cols列表可能会有所不同,所以这不会起作用。如何循环列列表以构建我的Select语句以最终获得我的Distinct值?

2 个答案:

答案 0 :(得分:4)

您可以为该任务实施自定义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();

答案 1 :(得分:0)

<svg width="640" height="480" viewbox="0 0 640 480" style="border: 1px dotted black;">
  <g transform="translate(270, 190)">
    <line x1="0" y1="0" x2="100" y2="0" stroke="black"></line>	
    <line x1="100" y1="0" x2="100" y2="100" stroke="black"></line>	
    <line x1="100" y1="100" x2="0" y2="100" stroke="black"></line>	
    <line x1="0" y1="100" x2="0" y2="0" stroke="black"></line>
  </g>
</svg>