Найти дубликаты в datatable с несколькими столбцами, кроме двух

Я новичок в кодировании и пытаюсь проверить электронную таблицу на наличие повторяющихся строк. В таблице 50 столбцов, и каждый столбец должен быть сравнен, за исключением двух. Если строки дублируются, они будут объединены в одну строку и суммы в Столбцах REQNUM и AUTHNUM будут суммированы. В большинстве найденных примеров используется » поле («имя столбца»)». Из-за большого количества столбцов я хочу использовать переменную, которая исключает те два, которые мне не нужны в compare.

Пример:


До. Точки представляют больше столбцов


COL1 / COL2 / COL3/…/ REQNUM / AUTHNUM


:——: | :——: | :—-: |…| :———-: | :————: |….


x / y / z/…| 1 | 1


x / y / z/…| 2 | 3

После


COL1 / COL2 / COL3/…/ REQNUM / AUTHNUM


——- | —— | —— | …|———— | ————|….


x / y / z/…| 3 | 4

Это код, который у меня есть, и он кажется близким, но не совсем правильным. Я ожидал результат только повторяющихся строк, поэтому позже я могу запустить его через каждый, который будет суммировать и удалять дополнительные строки. dtrow получает мне колонки, которые я хочу.(Спасибо Linq за исключением столбца). Когда я пытаюсь использовать эту переменную в моем запросе, я не получаю результатов, и если я удаляю » g.Count () > 1″ I get all the rows with them missing the two columns. Я хотел бы сохранить все эти два столбца в результатах и не добавлять их позже.

        var dtRow = dtExcel.Columns.Cast<DataColumn>().Where(c => c.ColumnName != "REQNUM" && c.ColumnName != "AUTHNUM").ToList();

        var checkExcel = dtExcel.Rows.Cast<DataRow>()
            .GroupBy(x => dtRow.Select(c => x[c]))
            .Where(g => g.Count() > 1)
            .Select(gr => gr);
        //.CopyToDataTable();

Спасибо Кену за помощь. Это сработало отлично для того, что мне нужно. Я использовал предложение groupby, чтобы объединить дубликат в одну строку и добавить числовые поля. также group by создает ключ, который я использую в операторе IF.

        var dtRow = dtExcel.Columns.Cast<DataColumn>().Where(c => c.ColumnName != "REQNUM" && c.ColumnName != "AUTHNUM").ToList();

        var excelDup = dtExcel.Rows.Cast<DataRow>()
            .GroupBy(x => String.Join("", dtRow.Select(c => x[c])))
            .Select(g => 
            {
                var row = g.First();
                row.SetField("REQNUM", g.Sum(x => x.Field<double>("REQNUM")));
                row.SetField("AUTHNUM", g.Sum(x => x.Field<double>("AUTHNUM")));
                return row;
            })
            .CopyToDataTable();

Я также использовал предложение where для создания переменной для datarow compare и без ключа.
// Создает переменную со всеми столбцами, кроме трех. Используется в следующем запросе
var dtExcelRow = dtExcel.Столбцы
.Отбрасывать.)(Где (c => c.ColumnName != «TITLE» & & c.ColumnName != «REQSTR» & & c.ColumnName != «AUTHSTR»).Толист();
var dtListRow = dtList.Столбцы
.Отбрасывать.)(Где (c => c.ColumnName != «TITLE» & & c.ColumnName != «REQSTR» & & c.ColumnName != «AUTHSTR»).Толист();

            // Querys create datarow list for compare
            IEnumerable<DataRow> eRow = dtExcel.AsEnumerable()
                .Where(w => dtExcelRow.Select(c => w[c]).Any())
                .Select(x => x);
            IEnumerable<DataRow> lRow = dtList.AsEnumerable()
                .Where(w => dtListRow.Select(c => w[c]).Any())
                .Select(x => x);

            // 1st compare gets list of new records that have changes or are new. 2nd is list of old records being change.
            var newRecords = eRow.AsEnumerable().Except(lRow.AsEnumerable(), DataRowComparer.Default);
            var oldRecords = lRow.AsEnumerable().Except(eRow.AsEnumerable(), DataRowComparer.Default);

1 ответ

  1. Вы не можете просто сгруппировать данные , dtRow.Select(c => x[c])потому что это aIEnumerable, они могут иметь то же самое содержимое, но они все еще разные IEnumerable.

    Если это так string, вы можете сгруппировать данные по соединенной строке:

    x => String.Join("", dtRow.Select(c => x[c]))