1

我有两节课:

public GeneralClassName 
{
    public GeneralClassName ()
    {
        SpecificList = new List<OtherClass>();
    }
    public string StringValue;
    public string OtherStringValue;
    public List<OtherClass> SpecificList;
}

public OtherClass
{
    public string Name;
    public string Number;
}

在 JSON 反序列化之后,我得到了一个不错List<GeneralClassName>的结果,我想要的结果是一个Dictionary<string, int>,它的值是里面的变量“数字”的总和List<OtherClass>List<GeneralClassName>而键是变量名称。

换句话说,我想按名称对数字分组求和。

现在,我唯一想到的是嵌套的 foreach,类似这样:

Dictionary<string, int> resultDictionary = new Dictionary<string, int>();
foreach(List<OtherClass> listOtherClass in bigListGeneralClass.Select(x => x.SpecificList))
{
    foreach(OtherClass otherClass in listOtherClass)
    {
        int value = 0;
        if(resultDictionary.ContainsKey(otherClass.Name))
        {
            resultDictionary[otherClass.Name] += otherClass.Number;
        }
        else
        {
            resultDictionary.Add(otherClass.Name, otherClass.Number);
        }
    }
}

虽然这个解决方案似乎运作良好,但我一点也不喜欢它。有没有更干净的方法来找到这个结果?也许通过一个不错的 LINQ 查询?

4

2 回答 2

6

由于您不使用可用于展平列表的任何GeneralClassName信息SelectMany。这个平面的OtherClass实例列表是按Name属性分组的。最后,组列表被转换为字典,组的键(也称为Name属性)是新属性的键,值是Number该组中所有值的总和:

var result = bigListGeneralClass.SelectMany(x => x.SpecificList)
                                .GroupBy(x => x.Name)
                                .ToDictionary(x => x.Key,
                                              x => x.Sum(y => y.Number));

这段代码假定它OtherClass.Number实际上是一个intnot a string。此假设也用于您的示例代码中的循环。
如果此假设不正确,请更改y.Numberint.Parse(CultureInfo.InvariantCulture, y.Number)
注意:如果无法解析任何数字,这将引发异常,因此您可能需要事先确保所有数字都包含有效数字。

于 2012-11-19T15:43:23.503 回答
0

试试这个:

Dictionary<string, int> result =
            bigListGeneralClass.SpecificList.GroupBy(sl => sl.Name)
                                .ToDictionary(group => group.Key, group => group.Sum(x => Int32.Parse(x.Number)));
于 2012-11-19T16:04:04.797 回答