【问题标题】:C# merge multiple lists based on timestampC#根据时间戳合并多个列表
【发布时间】:2016-09-19 19:39:21
【问题描述】:

我有一个数据集,它是 C# 中的对象列表,如下所示。

public class MotorDataModel
    {
        public DateTime timestamp { set; get; }
        public decimal MotorSpeed { set; get; }
        public decimal MotorTemp { set; get; }
        public decimal MotorKw{ set; get; }
    }


public class MotorModel
    {
        public string MotorName { set; get; }
        public List<MotorDataModel> MotorData { set; get; }
    }

当我进行查询时,我将返回 1 个或多个 MotorModel 记录(例如电机 1、2、3……),每个记录都有自己的时间戳,以及这些时间戳处的各种数据点。

然后我将此数据发送到一个 javascript 图表库,该库将数据作为数据表(例如电子表格格式),例如:

时间戳 |电机1:千瓦|电机 1:速度 |电机 1:温度 |电机 2:kW |电机 2:速度 ...

数据按行排列。数据将按时间戳分组,时间戳应该在几分钟内,以一致的增量(比如 15 分钟)。

计划是在 C# 中转换数据,将其转换为 JSON,并将其发送到图表库(Google Chart)。

我不必在 C# 中格式化,可以将 C# 中的对象列表数据转换为 JSON,然后在客户端用 javascript 重新格式化,但在服务器上转换似乎更好。

无论哪种方式,我都在努力研究如何将数据从多个对象列表转换为类似“数据表”的视图。

This answer via LINQ 似乎很接近,但我有多个设备列表,而不是定义的数量。

我也看过循环和构建数据表(或数组),但不确定哪种结构最有意义。

所以,如果有人做过类似的事情,或者有任何反馈,将不胜感激。

提供样本数据的建议格式

以下是 BlueMonkMN 提供的一些示例数据。请更新问题,提供代表您实际问题的样本数据。

     List<MotorModel> allData = new List<MotorModel>() {
        new MotorModel() {MotorName="Motor1", MotorData = new List<MotorDataModel> {
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 2, 56, 0), MotorSpeed=20.0M, MotorTemp=66.2M, MotorKw=5.5M},
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 3, 10, 30), MotorSpeed=10.0M, MotorTemp=67.0M, MotorKw=5.5M},
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 3, 25, 45), MotorSpeed=17.5M, MotorTemp=66.1M, MotorKw=5.8M},
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 3, 40, 23), MotorSpeed=22.2M, MotorTemp=65.8M, MotorKw=5.4M}
        }},
        new MotorModel() {MotorName="Motor2", MotorData = new List<MotorDataModel> {
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 2, 58, 0), MotorSpeed=21.0M, MotorTemp=67.2M, MotorKw=5.6M},
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 3, 11, 30), MotorSpeed=11.0M, MotorTemp=68.0M, MotorKw=5.6M},
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 3, 24, 45), MotorSpeed=18.5M, MotorTemp=67.1M, MotorKw=5.9M},
           new MotorDataModel(){timestamp=new DateTime(2016, 9, 18, 3, 39, 23), MotorSpeed=23.2M, MotorTemp=66.8M, MotorKw=5.5M}
        }}
     };

【问题讨论】:

  • 如果您可以提供一组非常小的样本数据来演示您尝试合并的实际数据的结构,您的问题会更清晰、更容易回答和测试。例如,您是否尝试合并多个 List 实例?
  • 您能否edit 分享您想要的 JSON 输出示例?
  • BlueMonkMN,是的,谢谢,上面的数据样本运行良好。让我完成下面的想法,我会回来的。谢谢!

标签: c# json linq object


【解决方案1】:

按照您的建议,一种可能性是遍历所有数据并构建表格。我建议使用Dictionary,以时间戳为键。每个时间戳可以有多个 MotorData,所以它可以有一个列表,如下所示:

Dictionary<DateTime, List<MotorDataModel>>

构建此表的代码 sn-p 如下所示:

List<MotorModel> motorModels;   // filled in previously
// build result structure in this dictionary:
Dictionary<DateTime, List<MotorDataModel>> table = new Dictionary<DateTime, List<MotorDataModel>>();
// iterate through all motors and their data, and fill in the table
foreach(MotorModel m in motorModels)
{
    foreach(MotorDataModel md in m.MotorData)
    {
        DateTime ts = md.timestamp;
        // if this is the first occurance of the timestamp, create new 'row'
        if (!table.ContainsKey(ts)) table[ts] = new List<MotorDataModel>();
        // add the data to the 'row' of this timestamp
        table[ts].Add(md);
    }
}

// output the table
foreach(DateTime ts in table.Keys)
{
    ...
    foreach(MotorDataModel md in table[ts])
    {
        ...
    }
}

【讨论】:

    【解决方案2】:

    我会使用 NewtonSoft 的 Json.NET。

    JObject o = new JObject();
    
    foreach (MotorModel mm in allData) {
        foreach (MotorDataModel mdm : mm.MotorData()) {
            string key = mdm.TimeStamp.ToString(); // Or do your own format
            o[key][mm.MotorName + ":kW"] = mdm.MotorKw;
            o[key][mm.MotorName + ":Speed"] = mdm.MotorSpeed;
            o[key][mm.MotorName + ":TEmp"] = mdm.MotorTemp;
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以尝试这样的方法来计算您的数据吗:

      var motorData = allData.SelectMany(x => x.MotorData).ToArray();
      var starting = motorData.Min(x => x.timestamp);
      var ending = motorData.Max(x => x.timestamp);
      var duration = ending.Subtract(starting);
      var blocks = (int)Math.Ceiling(duration.TotalMinutes / 15.0);
      
      var query =
          from b in Enumerable.Range(0, blocks)
          let s = starting.AddMinutes(b * 15.0)
          let e = starting.AddMinutes((b + 1.0) * 15.0)
          select new
          {
              Timestamp = s,
              MotorSpeedAverage =
                  motorData
                      .Where(x => x.timestamp >= s && x.timestamp < e)
                      .Average(x => x.MotorSpeed),
          };
      

      我得到这个结果:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-13
        • 1970-01-01
        • 2013-01-26
        • 1970-01-01
        • 1970-01-01
        • 2015-03-19
        • 2021-10-02
        • 2011-10-22
        相关资源
        最近更新 更多