C# 从具有多列的数据表中删除重复项的最佳方法是什么
对于多列,从数据表中删除重复项的最佳方法是什么?我的意思是下面的代码仅适用于单列C# 从具有多列的数据表中删除重复项的最佳方法是什么,c#,C#,对于多列,从数据表中删除重复项的最佳方法是什么?我的意思是下面的代码仅适用于单列 public DataTable RemoveDuplicateRows(DataTable dTable, string colName) { Hashtable hTable = new Hashtable(); ArrayList duplicateList = new ArrayList(); //Add list of all the unique item value to hash
public DataTable RemoveDuplicateRows(DataTable dTable, string colName)
{
Hashtable hTable = new Hashtable();
ArrayList duplicateList = new ArrayList();
//Add list of all the unique item value to hashtable, which stores combination of key, value pair.
//And add duplicate item value in arraylist.
foreach (DataRow drow in dTable.Rows)
{
if (hTable.Contains(drow[colName]))
duplicateList.Add(drow);
else
hTable.Add(drow[colName], string.Empty);
}
//Removing a list of duplicate items from datatable.
foreach (DataRow dRow in duplicateList)
dTable.Rows.Remove(dRow);
//Datatable which contains unique records will be return as output.
return dTable;
}
我尝试使用字符串[]colName。它在dTable.Rows.Remove(dRow)处抛出错误代码>
请建议。您可以在Datatable上使用Distinct。选择
参考此最简单、最易读的方法是使用Linq to DataTable
:
var groups = from r in dTable.AsEnumerable()
group r by new
{
Col1 = r.Field<String>("Column1"),
Col2 = r.Field<String>("Column2"),
};
// if you only want the first row of each group:
DataTable distinctTable = groups.Select(g => g.First()).CopyToDataTable();
您的RemoveDuplicateRows
方法:
public DataTable RemoveDuplicateRows(DataTable dTable, String[] colNames)
{
var hTable = new Dictionary<object[], DataRow>(new ObjectArrayComparer());
foreach (DataRow drow in dTable.Rows)
{
Object[] objects = new Object[colNames.Length];
for (int c = 0; c < colNames.Length; c++)
objects[c] = drow[colNames[c]];
if (!hTable.ContainsKey(objects))
hTable.Add(objects, drow);
}
// create a clone with the same columns and import all distinct rows
DataTable clone = dTable.Clone();
foreach (var kv in hTable)
clone.ImportRow(kv.Value);
return clone;
}
public DataTable RemoveDuplicateRows(DataTable dTable,String[]colNames)
{
var hTable=newdictionary(newObjectArrayComparer());
foreach(dTable.Rows中的数据行drow)
{
Object[]objects=新对象[colNames.Length];
for(int c=0;c
测试:
var table = new DataTable();
table.Columns.Add("Colum1", typeof(string));
table.Columns.Add("Colum2", typeof(int));
table.Columns.Add("Colum3", typeof(string));
Random r = new Random();
for (int i = 0; i < 100; i++)
{
table.Rows.Add("Colum1_" + r.Next(1, 10), r.Next(1, 10), "Colum3_" + r.Next(1, 10));
}
int rowCount = table.Rows.Count; // 100
var unique = RemoveDuplicateRows(table, new[] { "Colum1", "Colum2" });
int uniqueRowCount = unique.Rows.Count; // around 55-65
var table=newdatatable();
表.Columns.Add(“Colum1”,typeof(string));
表.列.添加(“列2”,类型(int));
表.Columns.Add(“Colum3”,typeof(string));
随机r=新随机();
对于(int i=0;i<100;i++)
{
表.行.添加(“列1_”+r.Next(1,10),r.Next(1,10),“列3_”+r.Next(1,10));
}
int rowCount=table.Rows.Count;//100
var unique=RemoveDuplicateRows(表,新[]{“Colum1”,“Colum2”});
int uniqueRowCount=unique.Rows.Count;//大约55-65岁
以下是您的代码,并对我的代码进行了几处修改。
其主要思想是向哈希表
(我的代码中的字典)中添加的不是一列的值,而是指定列的值,并以原子方式威胁这些值(就像单个值一样)
//您的代码只需稍加修改
公共DataTable RemovedUpplicateRows(DataTable dTable,string[]colNames)
{
//请注意,强类型字典已替换哈希表+它使用自定义比较器
var hTable=新字典();
var duplicateList=新的ArrayList();
//将所有唯一项值的列表添加到哈希表中,哈希表存储键、值对的组合。
//并在arraylist中添加重复的项值。
foreach(dTable.Rows中的数据行drow)
{
var dataRowInfo=新的dataRowInfo(drow,colNames);
if(hTable.ContainsKey(dataRowInfo))
重复列表。添加(drow);
其他的
添加(dataRowInfo,string.Empty);
}
//从datatable中删除重复项的列表。
foreach(重复列表中的数据行dRow)
dTable.Rows.Remove(dRow);
//包含唯一记录的Datatable将作为输出返回。
返回数据表;
}
//助手类
//包含指定列的值
内部密封类DataRowInfo
{
公共对象[]值{get;private set;}
公共DataRowInfo(DataRow DataRow,string[]列)
{
Values=columns.Select(c=>dataRow[c]).ToArray();
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(this,obj))
返回true;
var other=对象作为数据行信息;
如果(其他==null)
返回false;
回报等于(其他);
}
私有布尔等于(DataRowInfo其他)
{
if(this.Values.Length!=其他.Values.Length)
返回false;
for(int i=0;i
希望这会有所帮助
更新
代码简化了一点。:谢谢你的回答。我真的不明白这里的概念。我们在哪里删除重复项???@user1495475:添加了一些希望有用的注释。Tim:汇编缺少“AsEnumerable”。我尝试包含system.data.datatable仍然是相同的错误。有什么问题吗?@user1495475:您是否至少使用了.NET 35,并且是否添加了对system.data.DataSetExtensions.dll
的引用?Tim:Im使用目标框架作为版本2.0。我还没有使用您的参考system.data.DataSetExtensions,阿列克西:谢谢你的回答。我不认为这是一个更好的方法。我们没有一个简单的方法来解决这个问题吗???@user1495475:我已经简化了一些代码,恐怕我不能做更简单的事情了。顺便说一句,尽管该解决方案的代码比您发布的要多得多,但它并没有那个么复杂:它只是将值添加到哈希表数组(包装到helper数据结构中),而不是单个原语值。讨厌重新发布我自己的答案。看见
var table = new DataTable();
table.Columns.Add("Colum1", typeof(string));
table.Columns.Add("Colum2", typeof(int));
table.Columns.Add("Colum3", typeof(string));
Random r = new Random();
for (int i = 0; i < 100; i++)
{
table.Rows.Add("Colum1_" + r.Next(1, 10), r.Next(1, 10), "Colum3_" + r.Next(1, 10));
}
int rowCount = table.Rows.Count; // 100
var unique = RemoveDuplicateRows(table, new[] { "Colum1", "Colum2" });
int uniqueRowCount = unique.Rows.Count; // around 55-65
// your code with minor amends
public DataTable RemoveDuplicateRows(DataTable dTable, string[] colNames)
{
// note that strongly typed dictionary has replaced the hash table + it uses custom comparer
var hTable = new Dictionary<DataRowInfo, string>();
var duplicateList = new ArrayList();
//Add list of all the unique item value to hashtable, which stores combination of key, value pair.
//And add duplicate item value in arraylist.
foreach (DataRow drow in dTable.Rows)
{
var dataRowInfo = new DataRowInfo(drow, colNames);
if (hTable.ContainsKey(dataRowInfo))
duplicateList.Add(drow);
else
hTable.Add(dataRowInfo, string.Empty);
}
//Removing a list of duplicate items from datatable.
foreach (DataRow dRow in duplicateList)
dTable.Rows.Remove(dRow);
//Datatable which contains unique records will be return as output.
return dTable;
}
// Helper classes
// contains values of specified columns
internal sealed class DataRowInfo
{
public object[] Values { get; private set; }
public DataRowInfo(DataRow dataRow, string[] columns)
{
Values = columns.Select(c => dataRow[c]).ToArray();
}
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
return true;
var other = obj as DataRowInfo;
if (other == null)
return false;
return Equals(other);
}
private bool Equals(DataRowInfo other)
{
if (this.Values.Length != other.Values.Length)
return false;
for (int i = 0; i < this.Values.Length; i++)
{
if (AreObjectsEqual(this.Values[i], other.Values[i]))
return false;
}
return true;
}
private static bool AreObjectsEqual(object left, object right)
{
if (ReferenceEquals(left, right))
return true;
if (ReferenceEquals(left, null))
return false;
if (ReferenceEquals(right, null))
return false;
if (left.GetType() != right.GetType())
return false;
return left.Equals(right);
}
public override int GetHashCode()
{
unchecked
{
int hashCode = 0;
foreach (var value in this.Values)
{
hashCode = hashCode ^ ((value != null ? value.GetHashCode() : 0) * 397);
}
return hashCode;
}
}
}