我有数据表,其中包含许多重复行,我需要根据多个列从数据表中过滤这些行,以在结果数据表中获取不同的行....
Barcode Itemid PacktypeId
1 100 1
1 100 2
1 100 3
1 100 1
1 100 3
只需要包含packtypeid 1,2,3的行,其中第4行和第5行应该被删除
我尝试过使用两种方法,但没有一种方法可以获得更好的结果
数据表包含10个以上的列,但唯一的列是"条形码"," ItemID"," PackTypeID"
方法-1:
dt_Barcode = dt_Barcode.DefaultView.ToTable(true, "Barcode", "ItemID", "PackTypeID");
上面的方法过滤了行,但它只返回列3列值我需要整个10列值。
Method-2:
List<string> keyColumns = new List<string>();
keyColumns.Add("Barcode");
keyColumns.Add("ItemID");
keyColumns.Add("PackTypeID");
RemoveDuplicates(DataTable table, List<string> keyColumns)
{
var uniqueness = new HashSet<string>();
StringBuilder sb = new StringBuilder();
int rowIndex = 0;
DataRow row;
DataRowCollection rows = table.Rows;
int i = rows.Count;
while (rowIndex < i)
{
row = rows[rowIndex];
sb.Length = 0;
foreach (string colname in keyColumns)
{
sb.Append(row[colname]);
sb.Append("|");
}
if (uniqueness.Contains(sb.ToString()))
{
rows.Remove(row);
}
else
{
uniqueness.Add(sb.ToString());
rowIndex++;
}
}
Above Method返回异常,就像位置5没有行一样
答案 0 :(得分:2)
方法3:
我发现这个Linq方法非常有用
,而不是尝试2种方法 dt_Barcode = dt_Barcode.AsEnumerable().GroupBy(r => new { ItemID = r.Field<Int64>("ItemID"), PacktypeId = r.Field<Int32>("PackTypeID") }).Select(g => g.First()).CopyToDataTable();
答案 1 :(得分:0)
这是因为您删除了行。
如果你想保留相同的算法,而不是使用while (rowIndex < i)
使用这种形式的循环:
for (var rowIndex = rows.Count - 1; rowIndex >= 0; rowIndex--)
{
...
if (uniqueness.Contains(sb.ToString()))
{
rows.Remove(row);
rowIndex--;
}
...
}
答案 2 :(得分:0)
public void RemoveDuplicatesFromDataTable(ref DataTable table, List<string> keyColumns)
{
Dictionary<string, string> uniquenessDict = new Dictionary<string, string>(table.Rows.Count);
StringBuilder stringBuilder = null;
int rowIndex = 0;
DataRow row;
DataRowCollection rows = table.Rows;
string error = string.Empty;
try
{
while (rowIndex < rows.Count)
{
row = rows[rowIndex];
stringBuilder = new StringBuilder();
foreach (string colname in keyColumns)
{
try
{
if (row[colname].ToString() != string.Empty)
{
stringBuilder.Append(((string)row[colname]));
}
else
{
//If it comes here, means one of the keys are blank
error += "One of the key values is blank.";
}
}
catch (Exception ss)
{
error += "Error " + ss.Message + ".";
}
}
if (uniquenessDict.ContainsKey(stringBuilder.ToString()))
{
rows.Remove(row);
}
else
{
uniquenessDict.Add(stringBuilder.ToString().Replace(",", ""), string.Empty);
rowIndex++;
}
}
}
catch (Exception ex)
{
error = "Failed - " + ex.Message;
}
if(error != string.Empty)
Show`enter code here`(error);
}