根据列值从DataTable中删除重复项的最佳方法

时间:2015-06-10 14:06:59

标签: c# asp.net linq datatable

我有DataSet只包含一个Table,所以你可以说我在这里使用了DataTable。

您在下面看到的代码可以运行,但我希望有最好,最有效的方式来执行任务,因为我在这里使用了一些数据。

基本上,表中的数据应该在数据库中,当然主键 - 当然 - 必须是唯一的。

我使用的数据的主键位于名为Computer Name的列中。对于每个条目,我们在另一列date中也有一个日期。

我写了一个函数,在Computer Name列中搜索重复项,然后比较这些重复项的日期以删除除最新项之外的所有重复项。

我写的函数看起来像这样:

private void mergeduplicate(DataSet importedData)
{
    Dictionary<String, List<DataRow>> systems = new Dictionary<String, List<DataRow>>();
    DataSet importedDataCopy = importedData.Copy();
    importedData.Tables[0].Clear();
    foreach (DataRow dr in importedDataCopy.Tables[0].Rows)
    {
        String systemName = dr["Computer Name"].ToString();
        if (!systems.ContainsKey(systemName)) 
        {
            systems.Add(systemName, new List<DataRow>());
        }
        systems[systemName].Add(dr);
    }


    foreach (KeyValuePair<String,List<DataRow>> entry in systems) {
        if (entry.Value.Count > 1) {
            int firstDataRowIndex = 0;
            int secondDataRowIndex = 1;
            while (entry.Value.Count > 1) {
                DateTime time1 = Validation.ConvertStringIntoDateTime(entry.Value[firstDataRowIndex]["date"].ToString());
                DateTime time2 = Validation.ConvertStringIntoDateTime(entry.Value[secondDataRowIndex]["date"].ToString());

                //delete older entry
                if (DateTime.Compare(time1,time2) >= 0) {
                    entry.Value.RemoveAt(firstDataRowIndex);
                } else {
                    entry.Value.RemoveAt(secondDataRowIndex);
                }
            }
        }
        importedData.Tables[0].ImportRow(entry.Value[0]);
    }
}

我的问题是,由于此代码有效 - 执行任务的最佳,最快/最有效的方法是什么?

我感谢任何答案!

3 个答案:

答案 0 :(得分:2)

我认为这可以更有效地完成。使用private void mergeduplicate(DataSet importedData) { Dictionary<String, DataRow> systems = new Dictionary<String, DataRow>(); int i = 0; while (i < importedData.Tables[0].Rows.Count) { DataRow dr = importedData.Tables[0].Rows[i]; String systemName = dr["Computer Name"].ToString(); if (!systems.ContainsKey(systemName)) { systems.Add(systemName, dr); } else { // Existing date is the date in the dictionary. DateTime existing = Validation.ConvertStringIntoDateTime(systems[systemName]["date"].ToString()); // Candidate date is the date of the current DataRow. DateTime candidate = Validation.ConvertStringIntoDateTime(dr["date"].ToString()); // If the candidate date is greater than the existing date then replace the existing DataRow // with the candidate DataRow and delete the existing DataRow from the table. if (DateTime.Compare(existing, candidate) < 0) { importedData.Tables[0].Rows.Remove(systems[systemName]); systems[systemName] = dr; } else { importedData.Tables[0].Rows.Remove(dr); } } i++; } } 复制DataSet一次,然后将其再次复制到字典中,然后从字典中删除不必要的数据。我宁愿一次性删除不必要的信息。这样的事情怎么样:

ArrayList

答案 1 :(得分:0)

也许不是最有效的方式,但你说你欣赏任何答案

List<DataRow> toDelete =  dt.Rows.Cast<DataRow>()
                                .GroupBy(s => s["Computer Name"])
                                .SelectMany(grp => grp.OrderBy(x => x["date"])
                                .Skip(1)).ToList();
toDelete.ForEach(x => dt.Rows.Remove(x));

答案 2 :(得分:0)

您可以尝试使用CopyToDataTable,如下所示:

importedData.Tables[0] = importedData.Tables[0].AsEnumerable()
       .GroupBy(r => new {CN = r["Computer Name"], Date = r["date"]})
       .Select(g => g.OrderBy(r => r["Date"]).(First())
       .CopyToDataTable();