2015-12-31 1 views
2

У меня есть DataTable, что по существу выглядит следующим образом:Как выполнить итерацию по DataTable и получить группы строк на основе значения столбца?

Id | parentId 
__________________ 
1 | 100 
2 | 100 
3 | 200 
4 | 300 
5 | 300 
6 | 300 
7 | 400 
8 | 400 

Как вы можете видеть, каждая строка имеет уникальный идентификатор и назначается родителю на родителя ID (Int64). Кроме того, каждый родитель может содержать несколько строк.
В моем случае родительский билет - это билет в нашей системе, и строка является вложением в этот билет.

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

я могу добиться этого с если утверждение вроде этого (псевдо-код):

var currentParent = 0; 
foreach (var row in table.Rows) 
{ 
    if (row["parentId"] == currentParent) 
    { 
     // Same group 
    } 
    else 
    { 
     // New group 
    } 
    currentParent = row["parentId"]; 
} 

Это работает, но я чувствую, что это грязно, потому что, если первый элемент в группе 100 не удается, то все равно будет должны пройти оставшиеся 99 предметов.

Я пытался найти решение, которое использует LINQ и IEnumerable, чтобы захватить каждую группу строк и, возможно, поместить их в свои временные DataTable. Это упростит повторение и пропустить, если возникнет ошибка. К сожалению, я не уверен, какие функции я даже ищу, поэтому я застрял.

Я думал GroupBy звучало правильно и попытался это:

var results = table.AsEnumerable().GroupBy(row => row.Field<Int64>("parentId")); 

К сожалению, это возвращает только 4 строки, которые имеют смысл, как в моем примере есть только 4 разные родители.

Я искал что-то более, как это:

var count = temporaryDataTable.Rows.Count(); 

// After first "grab" of a group 'count' is 2 for parentId 100 
// temporaryDataTable contains Id values 1 & 2. 

// After second "grab" 'count' is 1 for parentId 200 
// temporaryDataTable contains Id value 3. 

// After third "grab" 'count' is 3 for parentId 300 
// temporaryDataTable contains Id values 4, 5 & 6. 

// Last "grab" 'count' is 2 for parentId 400 
// temporaryDataTable contains Id values 7 & 8. 

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

+0

Определив (4) группу, вы можете не то 'foreach' применить фильтр на столе? –

+0

Хорошая точка! Я сделаю некоторое тестирование и посмотрю, какой метод я считаю наиболее подходящим. Спасибо. – Equalsk

+0

Положите свой оператор select в цикл foreach от Claudiu - et voila! –

ответ

1

После того, как вы сгруппировали results, вы можете использовать этот цикл для перебора ваших групп:

foreach (var group in results) 
{ 
    // This will get the parentId value in the group. 
    var parentId = group.Key; 

    // This will get all the Ids contained in the group. 
    foreach (var Id in group) 
    { 
     // Do something with Id. If something goees wrong 
     // and you want to proceed with the next group, 
     // just put a break; inside this foreach. 
    } 
} 
+0

Ух, не могу поверить, что я был так близок! У меня была итерация результатов и ключ, не понимал, что это было так же просто, как итерация по группам. Спасибо! – Equalsk

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