简体   繁体   English

C#列表-分组依据-不带Linq

[英]C# List - Group By - Without Linq

I have an object: 我有一个对象:

IObject
{
    string Account,
    decimal Amount
}

How do I group by Account and Sum the Amount, returning a List without Linq. 如何按帐户分组并汇总金额,返回不含Linq的列表。

2.0 Framework ... that is why no Linq. 2.0框架...这就是为什么没有Linq。

Here is what I have: 这是我所拥有的:

    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);
        }


    }

Easiest answer: use LINQBridge and get all your LINQ to Objects goodness against .NET 2.0... works best if you can use C# 3 (ie VS2008 but targeting .NET 2.0). 最简单的答案:使用LINQBridge并针对.NET 2.0获得所有LINQ to Objects的好处...如果您可以使用C#3(即VS2008但以.NET 2.0为目标),则效果最佳。

If you really can't do that, you'll basically need to keep a dictionary from a key to a list of values. 如果您确实无法做到这一点,则基本上需要将字典从键保留到值列表。 Iterate through the sequence, and check whether it already contains a list - if not, add one. 遍历序列,并检查它是否已包含列表-如果没有,则添加一个。 Then add to whatever list you've found (whether new or old). 然后将其添加到找到的任何列表中(无论新旧)。

If you need to return the groups in key order, you'll need to also keep a list of keys in the order in which you found them. 如果需要按键顺序返回组,则还需要按找到键的顺序保留一个键列表。 Frankly it's a pain... just get LINQBridge instead :) 坦白说,这很痛苦...只需换成LINQBridge :)

(Seriously, each individual bit of LINQ is actually fairly easy to write - but it's also quite easy to make off-by-one errors, or end up forgetting to optimize something like Count() in the case where it's actually an ICollection<T> ... There's no need to reinvent the wheel here.) (严重的是,LINQ的每个位实际上都相当容易编写-但也很容易产生一个错误,或者在实际上是ICollection<T>的情况下最终忘记优化Count()类的东西。 ICollection<T> ...无需在这里重新发明轮子。)

EDIT: I was about to write some code, but then I noticed that you want a list returned... a list of what? 编辑:我正要写一些代码,但后来我发现,你想有一个列表返回...一个什么样的名单? A List<IList<IObject>> ? List<IList<IObject>> Or are you actually trying to group and sum in one go? 还是您实际上是在尝试一次汇总和汇总? If so, don't you want a list of pairs of key and amount? 如果是这样,您是否不需要键和金额对的列表? Or are you going to reuse the same class that you've already got for a single account, but as the aggregate? 还是要重用单个帐户已经拥有的同一个类,但要汇总使用? If it's the latter, here's some sample code: 如果是后者,下面是一些示例代码:

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;
}

Admittedly the extra efficiency here due to using a Dictionary for lookups will be pointless unless you've got really quite a lot of accounts... 诚然,除非您有很多帐户,否则使用Dictionary进行查找所带来的额外效率将毫无意义。

EDIT: If you've got a small number of accounts as per your comment, you could use: 编辑:如果根据您的评论,帐户数量很少,则可以使用:

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;
}

Use a dictionary to hold the results. 使用字典保存结果。 Locating an item in a dictionary is close to an O(1) operation, so it's a lot faster than searching for items in a list. 在字典中查找项目接近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);
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM