сравнить все строки в DataTable - определить дубликаты записей - PullRequest
1 голос
/ 19 марта 2009

Я хотел бы нормализовать данные в DataTable insertRows без ключа. Для этого мне нужно идентифицировать и пометить дубликаты записей, найдя их ID (import_id). После этого я выберу только отдельные. Подход, о котором я думаю, состоит в том, чтобы сравнить каждую строку со всеми строками в этой таблице данных insertRows

Столбцы в DataTable не известны во время разработки, и ключ отсутствует. С точки зрения производительности таблица будет содержать от 10 до 20 тысяч записей и около 40 столбцов

Как мне добиться этого, не жертвуя при этом производительностью?

Я пытался использовать linq, но я не знал, как динамически указывать критерии where Здесь я сравниваю имена и фамилии в цикле для каждой строки

</p> <blockquote> <pre><code>foreach (System.Data.DataRow lrows in importDataTable.Rows) { IEnumerable<System.Data.DataRow> insertRows = importDataTable.Rows.Cast<System.Data.DataRow>(); var col_matches = from irows in insertRows where String.Compare(irows["fname"].ToString(), lrows["fname"].ToString(), true).Equals(0) && String.Compare(irows["last_name"].ToString(), lrows["last_name"].ToString(),true).Equals(0) select new { import_id = irows["import_id"].ToString() }; }

Любые идеи приветствуются. Как найти похожие имена столбцов с помощью linq?> Мой похожий вопрос

Ответы [ 3 ]

2 голосов
/ 20 марта 2009

Самый простой способ сделать это без сложности O (n 2 ) - это использовать структуру данных, которая эффективно реализует операции Set, в частности, операцию Contains. К счастью .NET (по состоянию на 3.0) содержит объект HashSet , который делает это за вас. Чтобы использовать это, вам понадобится один объект, который инкапсулирует строку в вашей DataTable.

Если DataRow не будет работать, я рекомендую преобразовать соответствующие записи в строки, объединить их и поместить в HashSet. Перед тем, как вставить строку, проверьте, содержит ли HashSet ее (используя Contains). Если это так, вы нашли дубликат.

Edit:

Этот метод O (n).

1 голос
/ 20 марта 2009

Я не уверен, правильно ли я понял вопрос, но при работе с System.Data.DataTable должно работать следующее.

for (Int32 r0 = 0; r0 < dataTable.Rows.Count; r0++)
{
   for (Int32 r1 = r0 + 1; r1 < dataTable.Rows.Count; r1++)
   {
      Boolean rowsEqual = true;

      for (Int32 c = 0; c < dataTable.Columns.Count; c++)
      {
         if (!Object.Equals(dataTable.Rows[r0][c], dataTable.Rows[r1][c])
         {
            rowsEqual = false;
            break;
         }
      }

      if (rowsEqual)
      {
         Console.WriteLine(
            String.Format("Row {0} is a duplicate of row {1}.", r0, r1))
      }
   }
}
0 голосов
/ 20 марта 2009

Я не слишком осведомлен о LINQ, но вы можете использовать оператор .Distinct ()?

http://blogs.msdn.com/charlie/archive/2006/11/19/linq-farm-group-and-distinct.aspx

В вашем вопросе неясно, нужно ли вам конкретно определять дубликаты строк или вы просто хотите удалить их из запроса. Добавление «Distinct» удалит лишние экземпляры, хотя это не обязательно скажет вам, что они были.

...