【问题标题】:Using LINQ to generate Highchart column table data使用LINQ生成Highchart列表数据
【发布时间】:2020-11-20 06:58:58
【问题描述】:

我有文章数据列表List<Article>

class Article
{
  ....
  public string Author{get; set}
  public int ReadingNumber{get; set}
  public int LikeNumber{get; set}
  public int ForwardingNumber{get; set}
  ....
}

输入数据

List<Article> input = new List<Article>
        {
            new Article { Author = "author1", ReadingNumber = 49, LikeNumber = 55, ForwardingNumber = 21 },
            new Article { Author = "author1", ReadingNumber = 11, LikeNumber = 35, ForwardingNumber = 79 },
            new Article { Author = "author2", ReadingNumber = 25, LikeNumber = 77, ForwardingNumber = 39 },
        };

现在我不知道如何使用Linq或其他任何东西将其转换为Highchart列表数据,是这样的:

categories: ['author1','author2']

series: [{
        name: 'TotalReadingNumber',
        data: [60, 25]
    }, {
        name: 'TotalLikeNumber',
        data: [90, 77]
    }, {
        name: 'TotalForwardNumber',
        data: [100, 39]
    }]

我已经厌倦了使用 linq 和 Foreach 方法来生成数据:

var authorData=
    (from a in articleList
     group a by a.Author into g
     select new {
       Author = g.Key,
       TotalReading = g.Sum(a=>a.ReadingNumber),
       TotalLikes = g.Sum(a=>a.LikeNumber),
       .......
    }).ToList()

然后我使用ForEach方法获取我需要的每一个属性

               var totalReading = new AuthorData()
                {
                    name = "TotalReading",
                    data = new List<string>()
                };
                authorData.ForEach(a => totalRead.data.Add(a.TotalRead.ToString()));

最后我将它们组合成结果,

var result =
 {
    Authors=authorData.Select(a=>a.Author).ToList(),
    series = new List<AuthorData>{totalReading,totalLike,totalForwrad.....}
}

我认为这很复杂。如何简化此解决方案?

【问题讨论】:

  • 嗨@ichPotatodeCXY,您使用了highcharts 标签,但问题似乎与图表无关,而是与数据有关。如果您在使用 Highcharts 时遇到问题,请提供带有硬编码示例数据的演示。

标签: c# linq highcharts


【解决方案1】:

很遗憾,您没有说明您的输入是什么以及为什么它应该看起来像预期的输出。但我想这个解决方案应该建立你的预期输出。我使用反射来构建它。如果您添加或删除任何整数属性,它们将自动从您的输出字符串中添加或删除。

编辑:编辑问题后,我看到您需要计算属性的总和。这在您最初的问题中并不清楚。这是更新后的代码:

List<Article> input = new List<Article>
{
    new Article { Author = "author1", ReadingNumber = 49, LikeNumber = 55, ForwardingNumber = 74 },
    new Article { Author = "author1", ReadingNumber = 141, LikeNumber = 78, ForwardingNumber = 38 },
    new Article { Author = "author2", ReadingNumber = 106, LikeNumber = 38, ForwardingNumber = 39 },
};
        
var grouped = input.GroupBy(x => x.Author).Select(x => new
{
    Author = x.Key,
    TotalReadingNumber = x.Sum(y=>y.ReadingNumber),
    TotalLikeNumber = x.Sum(y=>y.LikeNumber),
    TotalForwardingNumber = x.Sum(y=>y.ForwardingNumber),
}).ToList();
    
StringBuilder output = new StringBuilder();
output.AppendLine("xAxis: {");
output.AppendLine("categories: [");
output.AppendLine(string.Join(",", input.Select(x => $"'{x.Author}'")));
output.AppendLine("]");
output.AppendLine("},"); 
output.Append("series: [");
bool first = true;
foreach(var property in grouped.GetType().GetGenericArguments().First().GetProperties().Where(x => x.PropertyType == typeof(int)))
{
    if(!first)
    {
        output.Append(", ");
    }
    output.AppendLine("{");
    output.AppendLine("name: 'Total" + property.Name + "',");
    output.AppendLine("data: [" + string.Join(",", grouped.Select(x => property.GetValue(x))) + "]");
    output.Append("}");
    first = false;
}
output.AppendLine("]");

如果您不想使用反射,因为您需要性能,或者因为您不想在更改 Article 类时动态更改输出,您也可以像我一样使用多个 string.Join 调用使用类别,并硬编码 TotalReadingNumberTotalLikeNumber 等值。

在线演示:https://dotnetfiddle.net/I88ZHD

【讨论】:

  • 这是一个很有前途的解决方案,但我想将结果作为 Json 字符串保存到数据库中,以便我可以在另一个控制器中读取它并将其返回到前面。您能否请检查我更新的代码,看看使用反射是否可以产生类似的结果。
  • 我更新了答案。现在它应该符合您的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 2015-02-09
  • 2016-11-29
  • 2019-06-25
  • 1970-01-01
相关资源
最近更新 更多