Пометить неуникальные строки в DataTable - PullRequest
5 голосов
/ 06 декабря 2010

У меня есть DataTable, который я хочу проверить, являются ли значения в трех столбцах уникальными. Если нет, последний столбец должен быть заполнен номером строки первого появления комбинации значений.

Например, эта таблица:

ID    Name    LastName    Age    Flag
-------------------------------------
1     Bart    Simpson     10      -
2     Lisa    Simpson      8      -
3     Bart    Simpson     10      -
4     Ned     Flanders    40      -
5     Bart    Simpson     10      -

Должно привести к такому результату:

Line  Name    LastName    Age    Flag
-------------------------------------
1     Bart    Simpson     10      -
2     Lisa    Simpson      8      -
3     Bart    Simpson     10      1
4     Ned     Flanders    40      -
5     Bart    Simpson     10      1

Я решил это путем итерации DataTable с двумя вложенными циклами for и сравнения значений. Хотя для небольшого объема данных это работает нормально, становится довольно медленным , когда DataTable содержит много строк.

У меня такой вопрос: каково самое лучшее / быстрое решение этой проблемы, учитывая, что объем данных может варьироваться, скажем, от 100 до 20000 строк?
Есть ли способ сделать это с помощью LINQ? (Я не слишком знаком с этим, но я хочу учиться!)

Ответы [ 2 ]

2 голосов
/ 06 декабря 2010

Я не могу комментировать, как вы можете сделать это в C # / VB с таблицей данных, но если бы вы могли переместить все это в SQL, ваш запрос выглядел бы так:

declare @t table (ID int, Name varchar(10), LastName varchar(10), Age int)
insert into @t values (1,     'Bart' ,   'Simpson',     10 )
insert into @t values (2,     'Lisa',    'Simpson' ,     8 )
insert into @t values (3,     'Bart',    'Simpson' ,    10 )
insert into @t values (4,     'Ned',     'Flanders' ,   40 )
insert into @t values (5 ,    'Bart',    'Simpson'   ,  10 )

select t.*,
(select min(ID) as ID
    from @t t2
    where t2.Name = t.Name
    and t2.LastName = t.LastName
    and t2.id < t.id)
from @t t

Здесь я определил таблицу для демонстрационных целей. Я полагаю, вы могли бы перевести это на LINQ.

0 голосов
/ 06 декабря 2010

Хорошо, я думаю, что получил ответ сам.Основываясь на предложении в ответе Джеймса Уайзмана, я попробовал кое-что с LINQ.

Dim myErrnrFnct = Function( current, first) If(first <> current, first, 0)
Dim myQuery = From row As DataRow In myDt.AsEnumerable _
                      Select New With { _
                        .LINE = row.Item("LINE"), _
                        .NAME = row.Item("NAME"), _
                        .LASTNAME = row.Item("LASTNAME"), _
                        .AGE = row.Item("AGE"), _
                        .FLAG = myErrnrFnct(row.Item("LINE"), myDt.AsEnumerable.First(Function(rowToCheck) _
                                                                                        rowToCheck.Item("NAME") = row.Item("NAME") AndAlso _
                                                                                        rowToCheck.Item("LASTNAME") = row.Item("LASTNAME") AndAlso _
                                                                                        rowToCheck.Item("AGE") = row.Item("AGE")).Item("LINE")) _
                      }

С помощью этого запроса я получаю именно тот результат, который описан в Вопросе.Функция myErrnrFnct необходима, потому что я хочу, чтобы столбец Flag имел значение 0, если нет другой строки с такими же значениями.

Чтобы снова получить DataTable из myQuery, мне пришлось добавить несколько описанных здесь расширений:
Как: реализовать CopyToDataTable, где универсальный тип T не является DataRow
И тогда эта строка будет делать:

Dim myNewDt As DataTable = myQuery.CopyToDataTable()

Кажется, это работает просто отлично.Любые предложения, чтобы сделать это лучше?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...