基于多列从数据表中删除重复行

时间:2014-11-11 08:29:40

标签: c# datatable dataview

我有数据表,其中包含许多重复行,我需要根据多个列从数据表中过滤这些行,以在结果数据表中获取不同的行....

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没有行一样

3 个答案:

答案 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);
        }