C#列表 - 分组 - 没有Linq

Mar*_*tin 1 c# group-by list

我有一个对象:

IObject
{
    string Account,
    decimal Amount
}
Run Code Online (Sandbox Code Playgroud)

如何按帐户分组并汇总金额,返回没有Linq的列表.

2.0框架......这就是为什么没有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);
        }


    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 15

最简单的答案:使用LINQBridge并获得针对.NET 2.0的所有LINQ to Objects优点...如果您可以使用C#3(即VS2008但针对.NET 2.0),效果最佳.

如果你真的不能这样做,你基本上需要保持一个字典从一个键到一个值列表.遍历序列,检查它是否已包含列表 - 如果没有,则添加一个.然后添加到您找到的任何列表(无论是新的还是旧的).

如果您需要按键顺序返回组,则还需要按照找到它们的顺序保留键列表.坦率地说,这是一个痛苦...只是得到LINQBridge :)

(说真的,LINQ的每一个单元实际上都很容易编写 - 但它也很容易做出一个一个错误,或者最终忘记优化的东西,比如Count()它实际上是ICollection<T>......没有必要在这里重新发明轮子.)

编辑:我正要写一些代码,但后来我注意到你想要一个列表返回...列表是什么?一个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;
}
Run Code Online (Sandbox Code Playgroud)

不可否认,由于使用Dictionaryfor for lookup,这里的额外效率将毫无意义,除非你有相当多的帐户......

编辑:如果你的评论中有少量帐户,你可以使用:

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;
}
Run Code Online (Sandbox Code Playgroud)