2015-03-25 2 views
1

Я пытаюсь создать метод, который при задании таблицы удалит похожие строки. То, что я думал сделать, это создать двойной цикл foreach, так что каждая отдельная строка в таблице будет сравниваться со всеми остальными.Метод, который сравнивает и удаляет все аналогичные строки в datatable

private void comparaeapagarowsiguais(DataTable table1) 
    { 
     foreach (DataRow row1 in table1.Rows) 
     { 
      foreach (DataRow row2 in table1.Rows) 
      { 
       var array1 = row1.ItemArray; 
       var array2 = row2.ItemArray; 

       if (array1.SequenceEqual(array2)) 
       { 
        table1.Rows.Remove(row2); 
       } 

      } 
     } 


    } 

Проблема заключается в том, что в какой-то момент, любая данная строка будет сравнивать с собой, и, таким образом, будет пытаться удалить себя (и я бы оканчиваться не рядами на всех). Но я хочу сохранить хотя бы одну из разных строк.

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

EDIT: Частичное решение

Я придумал решение, которое работает в моем случае. Это будет работать, если аналогичные строки будут немедленно расположены рядом друг с другом. (Если подобные строки разбросаны по всему столу он не будет работать)

private void comparalinhaseapaga(DataTable table1) 
    { //I will explain the try in the end 
     try 
     { 
      //you will run i for as long as you like 
      for (int i = 0; ;) 
      { 
       //you create 2 arrays from i, and i+1, this means you will compare 
       //the first 2 lines of the data table 
       var array1 = table1.Rows[i].ItemArray; 
       var array2 = table1.Rows[i + 1].ItemArray; 

       //if they are similar, it removes row at 1, and will go back to the cycle and 
       //proceed to compare row at 0 with the previously row at 2 
       if (array1.SequenceEqual(array2)) 
       { 
        table1.Rows.RemoveAt(i + 1); 
       } 
       else 
       { 
        //if they are not equal, it move next to row at 1, and compare it with row at 2 
        //once it gets here, the row 0 and row 1 are already different 
        //that's why it only works when the similar rows are adjacent to another 
        i++; 
       } 
      } 
     } 
     catch { } 
    } 

Попробовать и поймать это потому, что в какой-то момент он не будет иметь строку в позиции я + 1 для сравнения, и будет производить ошибка. Использование try/catch пропустит ошибку и продолжит, что вы можете сделать, поскольку все аналогичные строки уже удалены. Протестировано и обработано;)

Надеюсь, это полезно для кого-то.

Edit 2: Найдена чистое решение, просто взять этот код:

private DataTable RemoveDuplicatesRecords(DataTable dt) 
    { 
     //Returns just unique rows 
     var UniqueRows = dt.AsEnumerable().Distinct(DataRowComparer.Default); 
     DataTable dt2 = UniqueRows.CopyToDataTable(); 
     return dt2; 
    } 
+0

Какая цель? вы пытаетесь достичь массива типа данных? – McShep

+0

Это для удобства чтения конечному пользователю, ему не нужны 2 одинаковых строки, одного достаточно. – ng80092b

ответ

1

Вы можете изменить свой метод добавления следующей проверки

private void comparaeapagarowsiguais(DataTable table1) 
{ 
    foreach (DataRow row1 in table1.Rows) 
    { 
     foreach (DataRow row2 in table1.Rows) 
     { 
      if (row1 != row2) 
      { 
       var array1 = row1.ItemArray; 
       var array2 = row2.ItemArray; 

       if (array1.SequenceEqual(array2)) 
       { 
        table1.Rows.Remove(row2); 
       } 
      } 
     } 
    } 
} 

Таким образом, они не должны быть сравнены если начальная строка;)

Или вы можете использовать LINQ (как я писал в комментарии), используя этот код, чтобы выбрать только похожие строки, а затем удалить их:

private void comparaeapagarowsiguais(DataTable table1) 
{ 
    foreach (DataRow row1 in table1.Rows) 
    { 
     var toDelete = table1.AsEnumerable().Where(row => row.ItemArray.SequenceEqual(row1.ItemArray)); 

     foreach (DataRow r in toDelete) 
     { 
      table1.Rows.Remove(r); 
     } 
    } 
} 
+0

Очень хороший ответ. Я получаю System.InvalidOperationException был необработанным HResult = -2146233079 Message = Collection был изменен; операция перечисления может не выполняться. Эта ошибка в 'foreach (строка DataRow2 в таблице1.Строки) 'Но только тогда, когда у меня есть похожие строки, когда я этого не делаю, код работает нормально – ng80092b

+0

Я думаю, что это происходит потому, что оно меняет количество строк на лету, и поэтому, возможно, цикл foreach не такая уж отличная идея после все – ng80092b

+0

хорошо, если это происходит только тогда, когда есть похожие строки, вы можете поместить эту проверку внутри блока cactch try и удалить строку, если выбрано исключение (даже если я не думаю, что это лучшее решение) – oniramarf

1
private void comparaeapagarowsiguais(DataTable table1) 
    { int a=0; int b=0; 
     foreach (DataRow row1 in table1.Rows) 
     { a++; 
      b=0; 
      foreach (DataRow row2 in table1.Rows) 
      { b++; 
       if(a!=b) 
       { 
       var array1 = row1.ItemArray; 
       var array2 = row2.ItemArray; 

       if (array1.SequenceEqual(array2)) 
       { 
        table1.Rows.Remove(row2); 
       } 
       } 

      } 
     } 


    } 
2

Я считаю, что это может быть упрощено к группе по методу, это может быть достигнуто только с помощью LINQ. Затем просто выберите первый элемент каждой группы

это превратит ваш DataTable в перечислимый затем позволяет группировать значения вы не привычку дублировать

public IEnumerable<DataRow> test(DataTable myTable) 
    { 
     var results = myTable.AsEnumerable() 
      .GroupBy(datarow => datarow .ItemArray[1]).Select(y=> y.First()) ; 

     return results; 
    } 

или если его матч на все поля

public DataTable test(DataTable myTable) 
    { 
     var results = myTable.AsEnumerable().Distinct().CopyToDataTable() ; 

     return results; 
    } 
+0

Я думаю, что вы правы, я создал список индексов строки и попытался удалить их после. Но потом возникла другая проблема. Это проблема с проблемами. Я попытаюсь использовать linq и дать некоторую обратную связь прямо сейчас – ng80092b

+0

Я раньше не использовал linq, вы можете предоставить более подробную информацию? – ng80092b

+1

Можете ли вы привести пример datarow? Трудно с примера – McShep

Смежные вопросы