2009-11-30 3 views
3

У меня есть цикл:Агрегирования внутри цикла Еогеаспа

<% foreach (User usedBy in discountDto.UsedBy) 
    { %> 
    <%=usedBy.FullName%><br /> 
<% } %> 

, что часто приводит к нескольким строк с тем же именем:

Bob Smith 
Mark Thomas 
Mark Thomas 
Steve Jones 

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

Bob Smith 
Mark Thomas (2) 
Steve Jones 

ответ

9

Извините, что формат - неправильные инструменты "в руки" ...

foreach (User usedBy in discountDto.UsedBy.GroupBy(x => x.FullName)) 
{ 
    var count = usedBy.Count(); 
    %><%=usedBy.Key%><% 
     if(count>1) %><%=" (" + count + ")"%><% 
    %><br /> 
<% } %> 
+0

не ОП здесь, но заинтересован в ответ. Я получаю недопустимое исключение литья в строке foreach. «Невозможно передать объект типа« Группировка [System.String, SolutionName.User] », чтобы ввести« SolutionName.User ».» Где я иду не так? – jammus

+1

Я считаю, что GroupBy не собирается возвращать пользователя, а скорее IGrouping . Вам просто нужно изменить foreach (User usedBy в discountDto.UsedBy.GroupBy (x => x.FullName)) to foreach (IGrouping usedBy в discountDto.UsedBy.GroupBy (x => x. FullName)) –

+0

Попробуйте изменить строку foreach на: 'foreach (var usedBy в discountDto.UsedBy.GroupBy (x => x.FullName))' – Charlino

1
var aggregatedUsers=from users in discountDto.UsedBy 
            group user by user.FullName into result 
            select new 
             { 
              User=result.Key, 
              Count= result.Count(), 
             }; 
+0

Вам действительно не нужно ' в ... выберите' здесь. Запрос LINQ может завершиться с помощью 'group ... by ...', и в этом случае результатом будет 'IGrouping', который будет в основном эквивалентен вашему анонимному классу. –

+0

Это правда; подумать об этом, главная причина, по которой я использовал этот чрезмерный метод, заключается в том, что большинство случаев, в которых я использую группу, у меня есть еще одна совокупность, такая как LastLogin = result.Max (p => p.LastLogin). – JasonTrue

+0

Хотя подумайте об этом, использование анонимного типа означает, что вы вызовете метод Count() только один раз; если вы всегда показываете только счет, вам не нужна такая небольшая эффективность, но если вы решите отобразить счет или не на основе его значения, как указано выше, это избавит вас от дополнительной итерации по сгруппированным элементам , – JasonTrue

0

Попробуйте это: Пожалуйста, простите за плохой синтаксис ... мой Asp.Net ржавый, надеюсь, вы получите идею ...

<% 
    Dictionary<string,int> counts = new Dictionary<string, int>(); 
    foreach (User usedBy in discountDto.UsedBy) 
    { %> 
     <%if (counts.Contains(usedBy.FullName)) counts[usedBy.FullName]++; 
      else counts.Add(usedBy.FullName, 1);  
    } %> 
    <% foreach(string usdBy in counts) 
    { %> 
     <%=usdBy%><br /><% 
     <%if (counts[usdBy] > 1) 
     {%> 
      (<%=counts[usdBy];%>) <% 
     }%> 
    } %> 
+0

Вы забыли вывести счет во втором цикле. –

+0

На самом деле второй цикл даже не компилируется, потому что для переменной итерации вам нужен ключ KeyValuePair . –

+0

Не только второй цикл не использует правильный тип данных, он также пытается вывести с использованием несуществующей переменной. – Joshua

1

Что-то вроде этого работал для меня

foreach (var item in list.GroupBy(u => new {u.Surname, u.FirstName})) 
{ 
    %> 
    <%=Html.Encode(item.Key.FirstName)%> 
    <%=Html.Encode(item.Key.Surname)%> 
    <% 
    if (item.Count) > 1) 
    { 
     %> 
     (<%=item.Count%>) 
     <% 
    } 
} 
Смежные вопросы