2009-09-22 3 views
1

У меня есть объект:C# Список - группы - Без Linq

IObject 
{ 
    string Account, 
    decimal Amount 
} 

Как я группа по Счету и просуммировать объемы, возвращая список без Linq.

2.0 Framework ... вот почему нет Linq.

Вот что у меня есть:

ListofObjects = List<IObject>; 

    foreach (var object in objects) 
    { 
     var objectToAdd = new Object(object); 

     var oa = ListofObjects.Find(x => x.Account == objectToAdd.Account); 

     if (oa == null) 
     { 
      ListofObjects.Add(objectToAdd); 
     } 
     else 
     { 
      ListofObjects.Remove(oa); 
      oa.Amount = objectToAdd.Amount; 
      ListofObjects.Add(oa); 
     } 


    } 
+0

erm, вы пишете цикл. –

+0

Спасибо, у меня есть один, но то, что у меня кажется слишком сложным. – Martin

+0

Вы не показали, что такое ListofObjects, но это не выглядит ужасно эффективным ... я предполагаю, что у вас есть группа O (n^2). –

ответ

15

Самый простой ответ: использовать LINQBridge и получить все ваши LINQ к объектам благость против .NET 2.0 ... работает лучше, если вы можете использовать C# 3 (то есть VS2008, но таргетинг .NET 2.0).

Если вы действительно не можете этого сделать, вам в основном нужно будет сохранить словарь от ключа до списка значений. Итерации по последовательности и проверьте, содержит ли он уже список - если нет, добавьте его. Затем добавьте в список, который вы нашли (новый или старый).

Если вам нужно вернуть группы в порядке очереди, вам также необходимо сохранить список ключей в том порядке, в котором вы их нашли. Честно говоря, это боль ... просто возьмите LINQBridge :)

(Серьезно, каждый отдельный бит LINQ на самом деле довольно прост в написании, но также довольно легко сделать ошибки «за собой» или забыть оптимизировать что-то вроде Count() в том случае, когда это на самом деле ICollection<T> ... Там нет необходимости изобретать колесо здесь)

EDIT:. Я собирался написать код, но потом я заметил, что вы хотите список вернулся ... список чего? A List<IList<IObject>>? Или вы на самом деле пытаетесь группировать и суммировать за один раз? Если это так, вам не нужен список пар ключей и суммы? Или вы собираетесь повторно использовать тот же класс, который у вас уже есть для одной учетной записи, но как совокупность? Если это последнее, вот некоторые примеры кода:

public static IList<IObject> SumAccounts(IEnumerable<IObject> data) 
{ 
    List<IObject> ret = new List<IObject>(); 
    Dictionary<string, IObject> map = new Dictionary<string, IObject>(); 

    foreach (var item in data)   
    { 
     IObject existing; 
     if (!map.TryGetValue(item.Account, out existing)) 
     { 
      existing = new IObject(item.Account, 0m); 
      map[item.Account] = existing; 
      ret.Add(existing); 
     } 
     existing.Amount += item.Amount; 
    } 
    return ret; 
} 

Правда дополнительная эффективность здесь в связи с использованием Dictionary для поисков будет бессмысленно, если вы не получили на самом деле довольно много счетов ...

EDIT: Если у вас есть небольшое количество счетов, как на ваш комментарий, вы можете использовать:

public static IList<IObject> SumAccounts(IEnumerable<IObject> data) 
{ 
    List<IObject> ret = new List<IObject>(); 

    foreach (var item in data)   
    { 
     IObject existing = ret.Find(x => x.Account == item.Account); 
     if (existing == null) 
     { 
      existing = new IObject(item.Account, 0m); 
      ret.Add(existing); 
     } 
     existing.Amount += item.Amount; 
    } 
    return ret; 
} 
+0

dang! Я забыл о LINQBridge от Джо. И Джон так близок к 100 КБ ... +1!;) –

+0

Спасибо, но я сомневаюсь, что могу получить подписку, чтобы добавить его в свой проект, чтобы помочь 12 из 1000 строк кода. – Martin

+0

Я подозреваю, что вы обнаружите, что это поможет вам больше, чем это ... –

3

используйте словарь для хранения результатов. Поиск элемента в словаре близок к операции O (1), поэтому он намного быстрее, чем поиск элементов в списке.

Dictionary<string, decimal> sum = new Dictionary<string, decimal>(); 

foreach (IObject obj in objects) { 
    if (sum.ContainsKey(obj.Account)) { 
     sum[obj.Account].Amount += obj.Amount; 
    } else { 
     sum.Add(obj.Account, obj.Amount); 
    } 
} 
+0

Поиск записи в словаре быстрее, чем поиск в линейном списке, когда у вас много предметов ... для очень небольшого словаря/списка он может быть медленнее. Не забывайте, что O (...) является мерой того, как сложность изменяется с ростом N, а не с абсолютной операцией. –

+0

@Jon: Да, если предметов очень мало, словарь может быть медленнее, но тогда так мало времени, что это редко имеет значение. Если код работает так часто, что это проблема, тогда, вероятно, в любом случае это должно быть разрешено совершенно иначе. – Guffa

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