2012-04-30 4 views
3

Используя .NET 3.5, мне нужно сгруппировать DataTable несколькими столбцами, где имена столбцов содержатся в IEnumerable.LINQ - Group DataTable несколькими столбцами, определенными во время выполнения

// column source 
IEnumerable<string> columns; 
DataTable table; 

IEnumerable<IGrouping<object, DataRow>> groupings = table 
    .AsEnumerable() 
    .GroupBy(row => ???); 

Обычно ??? бы анонимный тип, как описано here, но мне нужно использовать columns в качестве источника столбца. Это возможно?

ответ

2

Самый простой способ сделать это - создать функцию, которая выбирает необходимые столбцы и создает хэш для сравнения. Я хотел бы сделать что-то вроде этого:

Func<DataRow, IEnumerable<string>, string> f = (row, cols) => 
    String.Join("|", cols.Select(col => row[col])); 

Эта функция принимает DataRow и IEnumerable<string>. Он проектирует IEnumerable<string> (имена столбцов) в соответствующие значения столбца (cols.Select(col => row[col]))), а затем соединяет эти значения с символом |. Я выбрал этот символ, потому что это маловероятный кандидат, который будет включен в ваши поля, но вы можете поменять его на другой разделитель.

Тогда просто

IEnumerable<IGrouping<object, DataRow>> groupings = table 
    .AsEnumerable() 
    .GroupBy(row => f(row, columns)); 

В идеале мы выбрали бы в лучшем типа - не строка связаны друг с другом с произвольным разделителем. Но я ожидаю, что выбор в объект вызовет проблемы из-за сравнения ссылочных типов, поскольку два объекта не равны, даже если они имеют одинаковые свойства.

+0

мне пришлось добавить бросок в проекции, чтобы заставить его работать: 'Func , строка> F = (строка, COLS) => string.join ("|", cols.Select (col => (string) row [col]). ToArray()); '- но мне интересно, можете ли вы объяснить, как эта строка действительно работает? '.GroupBy (строка => f (строка, столбцы))' - функция возвращает строку, но если вы замените ее на строку, она не сработает! Как известно группе, чтобы посмотреть на значения столбцов после того, как она построила строку в func? Я был бы счастлив, если бы вы могли указать мне на любые ресурсы, объясняющие это. –

+1

@ Джанна рада, что это помогло. Причина, по которой он работает, состоит в том, что строка, возвращаемая функцией, не просто «любая строка», это строка, содержащая значения столбца. Если значения столбцов совпадают для любых двух строк, то строки будут совпадать, и они будут «сгруппированы». –

+0

, поэтому он выполняет '(row => f (row, columns))', заканчивается значениями, такими как 'row => 1 | 10' или' row => 2 | 987', и они становятся ключами для группировок, так что если какой-либо из них повторяется, он будет сгруппирован с предыдущим. Хорошо, это имеет смысл. Благодаря! –

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