首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从此方法返回Dictionary<string、Dictionary<int、decimal>>?

如何从此方法返回Dictionary<string、Dictionary<int、decimal>>?
EN

Stack Overflow用户
提问于 2016-01-28 12:42:55
回答 1查看 1.8K关注 0票数 2

我有一个LINQ语句,它返回下面类的IQueryable。

类:

代码语言:javascript
复制
public class SupplierSummaryReport {
            public int Year { get; set; }
            public string SupplierName { get; set; }
            public decimal TurnOverValues { get; set; }
        }

例:{2012,Supplier1,90},{2011,Supplier2,95}

但是,我需要将这些数据转换为字典。我有我和一位朋友建立的扩展方法,但是我们在最后一节遇到了困难。

扩展方法:

代码语言:javascript
复制
public static Dictionary<TFirstKey, Dictionary<TSecondKey, TValue>> Pivot<TSource, TFirstKey, TSecondKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TFirstKey> firstKeySelector, Func<TSource, TSecondKey> secondKeySelector, Func<TSource, TValue> Value) {
            var retVal = new Dictionary<TFirstKey, Dictionary<TSecondKey, TValue>>();

            var l = source.ToLookup(firstKeySelector);
            foreach (var item in l) {
                var dict = new Dictionary<TSecondKey, TValue>();
                retVal.Add(item.Key, dict);
                var subdict = item.ToLookup(secondKeySelector);
                foreach (var subitem in subdict) {
                    dict.Add(subitem.Key, subitem.Value /*Insert value here*/);
                }
            }

            return retVal;
        }

我们这样称呼这个方法:

代码语言:javascript
复制
public Dictionary<string,Dictionary<int,decimal>> GetSupplierSummaryReportData(List<int> last5Years) {
            _ctx.Database.CommandTimeout = 5 * 60;
            //values - Gets the data required for the Supplier summary report in a hierachical order. E.g - {2012,Supplier1,3},{2011,Supplier1,4}
            var values = (from i in _ctx.Invoices
                          where i.Turnover == true
                          group i by new { i.AccountName, i.InvoiceDate.Year } into summ
                          select new APData.Audit.Models.ReportModels.SupplierSummaryReport {
                              Year = summ.Key.Year,
                              SupplierName = summ.Key.AccountName,
                              TurnOverValues = summ.Sum(r => r.VATAmount_Home ?? 0)
                          });

            //accounts - Get all the account names
            var accounts = (from i in _ctx.Invoices
                            where i.Turnover == true
                            group i by new { i.AccountName } into summ
                            select new {
                                summ.Key.AccountName
                            });

            /*crossJoin - select all SupplierNames from accounts and all years from last5Years and assign each SupplierName the last 5 years. Assign each turnover value null for each year.
            This is in preparation for the cross join as not all suppliers will have the last 5 year in data */

            var crossJoin = accounts.SelectMany(a => last5Years, (a, y) => new APData.Audit.Models.ReportModels.SupplierSummaryReport {
                Year = y,
                SupplierName = a.AccountName,
                TurnOverValues = 0
            });

            /*Join crossJoin and values together, wherever the join is empty, assign the cross join values. If not assign the turnover value from a*/

            var result =
                (from cj in crossJoin
                 join v in values
                 on new { cj.Year, cj.SupplierName }
                 equals new { v.Year, v.SupplierName } into lJoin
                 from a in lJoin.DefaultIfEmpty(new APData.Audit.Models.ReportModels.SupplierSummaryReport {
                     Year = cj.Year,
                     SupplierName = cj.SupplierName,
                     TurnOverValues = cj.TurnOverValues
                 })
                 select new APData.Audit.Models.ReportModels.SupplierSummaryReport {
                     Year = cj.Year,
                     SupplierName = cj.SupplierName,
                     TurnOverValues = a.TurnOverValues
                 }).OrderBy(r => r.SupplierName).ThenBy(r => r.Year);

            return result.Pivot(r => r.SupplierName, c => c.Year, y => y.TurnOverValues);

我们需要在字典中插入TurnOverValues的十进制值作为第三项。

预期成果:

代码语言:javascript
复制
{Supplier1, {2012,60}}, {Supplier2, {2014,90}}

如果有人需要更多的信息,请告诉我。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-28 13:07:13

但是,如果您拥有的是一个IEnumerable<SupplierSummaryReport>,并且您确信每个SupplierName, Year, TurnOver组合都是唯一的,或者可以是唯一的,那么ToDictionary就可以轻松地做到这一点:

代码语言:javascript
复制
var data = new List<SupplierSummaryReport> { ... };

// avoiding var just to verify correct result Type
Dictionary<string, Dictionary<int, decimal>> result = data
    .GroupBy(ssr => ssr.SupplierName)
    .ToDictionary(g1 => g1.Key, g1 => (
            g1.GroupBy(g2 => g2.Year)
              .ToDictionary(g3 => g3.Key, 
                            g3 => g3.First().TurnOverValues))
      );

也许g3.First()应该变成.Single()或者.Sum()什么的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35061838

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档