問題已編輯。見評論。更改以斜體顯示。
我有以下由 ID 標識的多個物理設備生成的有序(啟動/停止)事件串列。為簡單起見,僅顯示一臺設備的資料。
Date Hour ID Event IsStart
18/10/2021 10:35:22 1 DeviceConnected True
18/10/2021 10:20:10 1 DeviceConnected True
18/10/2021 10:12:20 1 DeviceConnected False
18/10/2021 10:12:19 1 DeviceConnected False
18/10/2021 08:24:14 1 DeviceConnected True
在給定的時間段內,通常是 24 小時,我不能有兩個或多個連續的啟動或停止。我需要洗掉“重復項”。
在上面的示例中,這意味著在使用 linq 應用過濾器后:
Date Hour ID Event IsStart
18/10/2021 10:20:10 1 DeviceConnected True
18/10/2021 10:12:19 1 DeviceConnected False
18/10/2021 08:24:14 1 DeviceConnected True
開始之后應該是停止或什么都不做,反之亦然。
這是一個典型的空島問題,對吧?讓我們將 Island number 添加到初始資料集。除非我錯了,否則我們應該以這樣的方式結束:
Date Hour ID Event IsStart Island
18/10/2021 10:35:22 1 DeviceConnected True 3
18/10/2021 10:20:10 1 DeviceConnected True 3
18/10/2021 10:12:20 1 DeviceConnected False 2
18/10/2021 10:12:19 1 DeviceConnected False 2
18/10/2021 08:24:14 1 DeviceConnected True 1
我可以用 Linq 做到這一點嗎?如果是這樣,我應該只能保留島上的第一個記錄。
uj5u.com熱心網友回復:
我不認為你可以用開箱即用的 LINQ 函式來完成這個,但是通過撰寫一個快速的“滯后”擴展方法,你可以用一個 LINQ 陳述句來完成它:
public static class EnumerableExtensions
{
public static IEnumerable<TResult> Lag<TSource, TResult>(
this IEnumerable<TSource> source,
TSource defaultLagValue,
Func<TSource, TSource, TResult> resultSelector
)
{
TSource lagValue = defaultLagValue;
foreach (var item in source)
{
yield return resultSelector(item, lagValue);
lagValue = item;
}
}
}
然后為了這個答案的目的,我正在創建一個類來保存資料(您應該已經擁有):
public class Event
{
public DateTime Date { get; set; }
public string Name { get; set; }
public bool IsStart { get; set; }
}
然后,您將如何運行它:
var data = new List<Event>();
data.Add(new Event { Date = new DateTime(2021, 10, 18, 10, 35, 22), Name = "DeviceConnected", IsStart = true });
data.Add(new Event { Date = new DateTime(2021, 10, 18, 10, 20, 10), Name = "DeviceConnected", IsStart = true });
data.Add(new Event { Date = new DateTime(2021, 10, 18, 10, 12, 20), Name = "DeviceConnected", IsStart = false });
data.Add(new Event { Date = new DateTime(2021, 10, 18, 10, 12, 19), Name = "DeviceConnected", IsStart = false });
data.Add(new Event { Date = new DateTime(2021, 10, 18, 8, 24, 14), Name = "DeviceConnected", IsStart = true });
List<Event> filteredData = data
.OrderBy(e => e.Date)
.Lag(null, (e, lag) => new {
Event = e,
PreviousItem = lag,
})
.Where(x => x.PreviousItem == null || x.Event.IsStart != x.PreviousItem.IsStart)
.Select(x => x.Event)
.OrderByDescending(e => e.Date)
.ToList();
之后,filteredData應該包含與此類似的預期輸出:
Date Hour Event IsStart
18/10/2021 10:20:10 DeviceConnected True
18/10/2021 10:12:19 DeviceConnected False
18/10/2021 08:24:14 DeviceConnected True
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/345370.html
上一篇:C#linq運算子作為變數
