Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在时间序列中查找开始和停止_C#_.net_Linq - Fatal编程技术网

C# 在时间序列中查找开始和停止

C# 在时间序列中查找开始和停止,c#,.net,linq,C#,.net,Linq,我想了解是否有方法使用linq exp查找给定时间序列的所有开始和停止窗口(由开始和结束值分隔)。 我知道这可以通过正常的循环来实现,但如果可能的话,我喜欢扩展我的知识 数据存储在有序的“标记数据”列表中(list) 当数据内容完全交替时,最简单的方法是: timestamp | tag | value 2018-12-01 00:10:00.000 | extrg_01 | 1 2018-12-01 00:15:02.000 | extrg_01 |

我想了解是否有方法使用linq exp查找给定时间序列的所有开始和停止窗口(由开始和结束值分隔)。 我知道这可以通过正常的循环来实现,但如果可能的话,我喜欢扩展我的知识

数据存储在有序的“标记数据”列表中(
list

当数据内容完全交替时,最简单的方法是:

timestamp               | tag       | value
2018-12-01 00:10:00.000 | extrg_01  | 1
2018-12-01 00:15:02.000 | extrg_01  | 0
2018-12-01 00:25:50.000 | extrg_01  | 1
2018-12-01 00:45:11.000 | extrg_01  | 0
在这一点上,给定初始值=1和结束值=0,结果将是沿着以下几条线:

timestamp_start         |timestamp_end              | tag       | nrOfSeconds
2018-12-01 00:10:00.000 |2018-12-01 00:15:02.000    | extrg_01  | 302
2018-12-01 00:25:50.000 |2018-12-01 00:45:01.000    | extrg_01  | 1161
但也可能存在一些不需要说明的“脏”数据:

timestamp               | tag       | value
2018-12-01 00:10:00.000 | extrg_01  | 1
2018-12-01 00:12:02.000 | extrg_01  | 1
2018-12-01 00:15:02.000 | extrg_01  | 0
2018-12-01 00:16:01.000 | extrg_01  | 0
2018-12-01 00:25:50.000 | extrg_01  | 1
2018-12-01 00:45:11.000 | extrg_01  | 0
在这种情况下,最终结果不应与第一个示例不同,因为不考虑定义初始值(在这种情况下为was=1)之后的所有值,同样,在计算中只考虑第一个最终值(在这种情况下为was=0)

我忘记添加我正试图编辑的linq表达式以获得结果: 不幸的是,我无法理解如何在这个.Zip中添加where条件(如果可能的话)来查找特定的值,并遵守时间条件来始终查找下一个可用的值

var diffs = tagDataList.Skip(1)
            .Zip(tagDataList,
                (curr, prev) => new
                {
                    CurrTag = curr.Tag,
                    CurrValue = curr.Value,
                    CurrDate = curr.Timestamp,
                    PrevDate = prev.Timestamp,
                    DiffToPrev = Math.Abs((curr.Timestamp - prev.Timestamp).TotalSeconds)
                })
            .ToList();

可能有很多方法可以做到这一点。我要试一试:

我假设您希望分别处理不同的标记。这是我的方法:

  • 按标记对条目进行分组
  • 每组:
  • 从列表开头删除值为0的所有条目
  • 如果有两个或多个相邻条目具有相同的值,则仅保留第一个条目。
    • 现在我们有了一个列表,从值1开始,在1和0之间交替
  • 将1与0压缩在一起以计算时间跨度
  • 最后将每组的所有结果展平
  • 我使用了以下测试数据:

    var list = new List<TagData> {
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:09:00.000"), Tag = "extrg_01", Value = 0 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:10:00.000"), Tag = "extrg_01", Value = 1 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:10:00.000"), Tag = "extrg_02", Value = 1 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:12:02.000"), Tag = "extrg_01", Value = 1 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:15:02.000"), Tag = "extrg_01", Value = 0 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:16:01.000"), Tag = "extrg_01", Value = 0 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:15:02.000"), Tag = "extrg_02", Value = 0 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:25:50.000"), Tag = "extrg_01", Value = 1 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:45:11.000"), Tag = "extrg_01", Value = 0 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:25:50.000"), Tag = "extrg_02", Value = 1 },
        new TagData { Timestamp = DateTime.Parse("2018-12-01 00:45:11.000"), Tag = "extrg_02", Value = 0 },
    };
    
    代码:


    我是作为一个电子计算器做的,所以我可以用foreach。我添加了一个属性,以便代码同时返回开始时间和结束时间

    sing System;
    using System.Collections.Generic;
    using System.Collections;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    
    namespace ConsoleApplication94
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<TagData> list = new List<TagData>() {
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:10:00.000"), Tag = "extrg_01", Value = 1},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:12:02.000"), Tag = "extrg_01", Value = 1},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:15:02.000"), Tag = "extrg_01", Value = 0},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:16:01.000"), Tag = "extrg_01", Value = 0},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:25:50.000"), Tag = "extrg_01", Value = 1},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:45:11.000"), Tag = "extrg_01", Value = 0}
                };
    
                TagData data = new TagData(list);
    
                foreach(TagData tagData in data)
                {
                    DateTime start = tagData.Timestamp;
                    DateTime end = tagData.Endstamp;
                    double seconds = tagData.numberOfSeconds;
                }
    
            }
        }
        class TagData : IEnumerator<TagData>
        {
            public DateTime Timestamp { get; set; }
            public string Tag { get; set; }
            public double Value { get; set; }
            public DateTime Endstamp { get; set; }
            public double numberOfSeconds;
    
            private List<TagData> listData;
            private int curIndex;
            private int endIndex;
            private TagData curTagData;
    
            public TagData() { }
            public TagData(List<TagData> collection)
            {
                listData = collection;
                curIndex = -1;
                endIndex = -1;
                curTagData = default(TagData);
    
            }
    
            public bool MoveNext()
            {
                if (curIndex != -1) curIndex = endIndex;
                while ((++curIndex < listData.Count()) && (listData[curIndex].Value != 1)) { }
                if (curIndex < listData.Count())
                {
                    endIndex = curIndex;
                    while ((endIndex < listData.Count()) && (listData[endIndex].Value != 0)) endIndex++;
                    if (endIndex >= listData.Count()) return false;
                    listData[curIndex].Endstamp = listData[endIndex].Timestamp;
                    listData[curIndex].numberOfSeconds = (listData[curIndex].Endstamp - listData[curIndex].Timestamp).TotalSeconds;
                }
                else
                {
                    return false;
                }
                curTagData = listData[curIndex];
                return true;
            }
    
            public void Reset() { curIndex = -1; endIndex = -1; }
    
            void IDisposable.Dispose() { }
    
            public TagData Current
            {
                get { return curTagData; }
            }
    
    
            object IEnumerator.Current
            {
                get { return Current; }
            }
    
            public TagData  GetEnumerator()
            {
                return new TagData(listData);
            }
    
        }
    }
    
    sing系统;
    使用System.Collections.Generic;
    使用系统集合;
    使用System.Linq;
    使用系统文本;
    使用System.Net.Sockets;
    Net系统;
    命名空间控制台应用程序94
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    列表=新列表(){
    new TagData(){Timestamp=DateTime.Parse(“2018-12-01 00:10:00.000”),Tag=“extrg_01”,Value=1},
    new TagData(){Timestamp=DateTime.Parse(“2018-12-01 00:12:02.000”),Tag=“extrg_01”,Value=1},
    new TagData(){Timestamp=DateTime.Parse(“2018-12-01 00:15:02.000”),Tag=“extrg_01”,Value=0},
    new TagData(){Timestamp=DateTime.Parse(“2018-12-01 00:16:01.000”),Tag=“extrg_01”,Value=0},
    new TagData(){Timestamp=DateTime.Parse(“2018-12-01 00:25:50.000”),Tag=“extrg_01”,Value=1},
    new TagData(){Timestamp=DateTime.Parse(“2018-12-01 00:45:11.000”),Tag=“extrg_01”,Value=0}
    };
    TagData数据=新的TagData(列表);
    foreach(TagData TagData in data)
    {
    DateTime start=tagData.Timestamp;
    DateTime end=tagData.Endstamp;
    双秒=tagData.numberOfSeconds;
    }
    }
    }
    类标记数据:IEnumerator
    {
    公共日期时间时间戳{get;set;}
    公共字符串标记{get;set;}
    公共双值{get;set;}
    公共日期时间结束戳{get;set;}
    公共双精度秒数;
    私有列表数据;
    私人国际库林德斯;
    私有内部索引;
    私有标记数据;
    公共标记数据(){}
    公共标记数据(列表集合)
    {
    listData=收集;
    curIndex=-1;
    endIndex=-1;
    curTagData=默认值(TagData);
    }
    公共图书馆
    {
    如果(curIndex!=-1)curIndex=endIndex;
    而(++curIndex=listData.Count())返回false;
    listData[curIndex].Endstamp=listData[endIndex].Timestamp;
    listData[curIndex].numberOfSeconds=(listData[curIndex].Endstamp-listData[curIndex].Timestamp).TotalSeconds;
    }
    其他的
    {
    返回false;
    }
    curTagData=listData[curIndex];
    返回true;
    }
    public void Reset(){curIndex=-1;endIndex=-1;}
    void IDisposable.Dispose(){}
    当前公共标记数据
    {
    获取{return curTagData;}
    }
    对象IEnumerator.Current
    {
    获取{返回当前;}
    }
    公共标记数据GetEnumerator()
    {
    返回新的标记数据(listData);
    }
    }
    }
    
    基于安徒生的分类和种子数据:

    var z = list
            .Where((t, index) => t.Value == 1 && list[index - 1].Value != 1)
            .Select(t =>
                new TagSummary
                {
                    TimestampStart = t.Timestamp,
                    TimestampEnd = list.First(x => x.Timestamp > t.Timestamp && x.Value == 0).Timestamp,
                    Tag = t.Tag
                }
            );
    /*
    OUTPUT:
    Start: 01.12.2018 0:10:00, End: 01.12.2018 0:15:02, Diff: 00:05:02, Tag: extrg_01
    Start: 01.12.2018 0:25:50, End: 01.12.2018 0:45:11, Diff: 00:19:21, Tag: extrg_01
    Start: 01.12.2018 0:25:50, End: 01.12.2018 0:45:11, Diff: 00:19:21, Tag: extrg_02
    */
    

    最好的方法是创建一个IEnunerate方法,从列表中获取开始/停止时间。您可以使用下一个。Try:class TagData:IEnumeratory您可以尝试使用聚合方法,但我不确定这与编写普通循环相比是否特别可读。是否提供要转换为LINQ的普通循环?当“index”为0并转到-1时,抛出“index not in the interval”。可能的解决方案:
    。其中((t,index)=>(index>1?t.Value==1&&listOfExlusionTriggers[index-1]。Value!=1:t.Value==1))
    是的,标记必须单独管理,并且按照我的要求使用linq表达式。我已经用普通循环实现了一个解决方案。
    var summaries =
        list.GroupBy(tagdata => tagdata.Tag) // Step (1)
        .Select(group => // Step (2)
        {
            var data = group
                .SkipWhile(tagdata => tagdata.Value == 0) // Step (2.1)
                .Aggregate(new List<TagData>(), (acc, tagdata) => // Step (2.2)
                {
                  if (acc.LastOrDefault()?.Value != tagdata.Value)
                      acc.Add(tagdata);
                  return acc;
                });
    
            var ones = data.Where(datatag => datatag.Value == 1);
            var zeros = data.Where(datatag => datatag.Value == 0);
            var result = ones.Zip(zeros, (startTag, endTag) => { // Step (2.3)
                return new TagSummary { TimestampStart = startTag.Timestamp, TimestampEnd = endTag.Timestamp, Tag = startTag.Tag };
            });
    
            return result;
        })
        .SelectMany(x => x); // Step (3)
    
    Console.WriteLine("timestamp_start     | timestamp_end       | tag      | nrOfSeconds");
    foreach (var summary in summaries)
        Console.WriteLine($"{summary.TimestampStart:yyyy-MM-dd HH:mm:ss} | {summary.TimestampEnd:yyyy-MM-dd HH:mm:ss} | {summary.Tag,-8} | {summary.TimeSpan.TotalSeconds:0}");
    
    timestamp_start     | timestamp_end       | tag      | nrOfSeconds
    2018-12-01 00:10:00 | 2018-12-01 00:15:02 | extrg_01 | 302
    2018-12-01 00:25:50 | 2018-12-01 00:45:11 | extrg_01 | 1161
    2018-12-01 00:10:00 | 2018-12-01 00:15:02 | extrg_02 | 302
    2018-12-01 00:25:50 | 2018-12-01 00:45:11 | extrg_02 | 1161
    
    sing System;
    using System.Collections.Generic;
    using System.Collections;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    
    namespace ConsoleApplication94
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<TagData> list = new List<TagData>() {
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:10:00.000"), Tag = "extrg_01", Value = 1},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:12:02.000"), Tag = "extrg_01", Value = 1},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:15:02.000"), Tag = "extrg_01", Value = 0},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:16:01.000"), Tag = "extrg_01", Value = 0},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:25:50.000"), Tag = "extrg_01", Value = 1},
                    new TagData() { Timestamp = DateTime.Parse("2018-12-01 00:45:11.000"), Tag = "extrg_01", Value = 0}
                };
    
                TagData data = new TagData(list);
    
                foreach(TagData tagData in data)
                {
                    DateTime start = tagData.Timestamp;
                    DateTime end = tagData.Endstamp;
                    double seconds = tagData.numberOfSeconds;
                }
    
            }
        }
        class TagData : IEnumerator<TagData>
        {
            public DateTime Timestamp { get; set; }
            public string Tag { get; set; }
            public double Value { get; set; }
            public DateTime Endstamp { get; set; }
            public double numberOfSeconds;
    
            private List<TagData> listData;
            private int curIndex;
            private int endIndex;
            private TagData curTagData;
    
            public TagData() { }
            public TagData(List<TagData> collection)
            {
                listData = collection;
                curIndex = -1;
                endIndex = -1;
                curTagData = default(TagData);
    
            }
    
            public bool MoveNext()
            {
                if (curIndex != -1) curIndex = endIndex;
                while ((++curIndex < listData.Count()) && (listData[curIndex].Value != 1)) { }
                if (curIndex < listData.Count())
                {
                    endIndex = curIndex;
                    while ((endIndex < listData.Count()) && (listData[endIndex].Value != 0)) endIndex++;
                    if (endIndex >= listData.Count()) return false;
                    listData[curIndex].Endstamp = listData[endIndex].Timestamp;
                    listData[curIndex].numberOfSeconds = (listData[curIndex].Endstamp - listData[curIndex].Timestamp).TotalSeconds;
                }
                else
                {
                    return false;
                }
                curTagData = listData[curIndex];
                return true;
            }
    
            public void Reset() { curIndex = -1; endIndex = -1; }
    
            void IDisposable.Dispose() { }
    
            public TagData Current
            {
                get { return curTagData; }
            }
    
    
            object IEnumerator.Current
            {
                get { return Current; }
            }
    
            public TagData  GetEnumerator()
            {
                return new TagData(listData);
            }
    
        }
    }
    
    var z = list
            .Where((t, index) => t.Value == 1 && list[index - 1].Value != 1)
            .Select(t =>
                new TagSummary
                {
                    TimestampStart = t.Timestamp,
                    TimestampEnd = list.First(x => x.Timestamp > t.Timestamp && x.Value == 0).Timestamp,
                    Tag = t.Tag
                }
            );
    /*
    OUTPUT:
    Start: 01.12.2018 0:10:00, End: 01.12.2018 0:15:02, Diff: 00:05:02, Tag: extrg_01
    Start: 01.12.2018 0:25:50, End: 01.12.2018 0:45:11, Diff: 00:19:21, Tag: extrg_01
    Start: 01.12.2018 0:25:50, End: 01.12.2018 0:45:11, Diff: 00:19:21, Tag: extrg_02
    */