我正在寻找一个"窗口"功能类似于F#' Seq.windowed
或反应扩展程序Window
。看起来它会由Select-Object
(已经具有take / skip功能)之类的提供,但它不是。
如果没有任何可用的东西,任何有关实施"窗口"的想法没有不必要的程序循环?
我正在寻找适合PowerShell管道的东西。
答案 0 :(得分:3)
您需要使用某种队列来累积和旋转足够的先前管道项:
function Window {
param($Size)
begin {
$Queue = [Collections.Queue]::new($Size)
}
process {
$Queue.Enqueue($_)
if($Queue.Count -eq $Size) {
@(
,$Queue.ToArray()
[void]$Queue.Dequeue()
)
}
}
}
你可以像这样使用它:
1..10 | Window 4 | Window 3 | Format-Custom -Expand CoreOnly
答案 1 :(得分:1)
据我所知,没有这样的内置功能。 PowerShell对管道的处理,特别是它对展开枚举的强烈坚持,使得编写一个函数来管道变得有点困难,但作为一般表达式:
$a = 1..10 # an array contain 1 through 10
$w = 4 # window size of 4
0..($a.Length-$w) | ForEach-Object -Process {
$a[$_..($_+$w-1)]
}
这会处理您想要的窗口数组。这样更容易看到:
0..($a.Length-$w) | ForEach-Object -Process {
"This is my window: $($a[$_..($_+$w-1)])"
}
问题是,如果您尝试以这种方式执行上述操作:
0..($a.Length-$w) | ForEach-Object -Process {
$a[$_..($_+$w-1)]
} | ForEach-Object -Process {
"This is my window: $_"
}
你会非常失望,因为“窗口”数组在被传送到ForEach-Object
之前已展开;你编写的任何管道函数都会遇到问题。
在函数中没有办法补偿它,你必须小心在ForEach-Object
块中使用它,因为即使在赋值:
$myWindows = 0..($a.Length-$w) | ForEach-Object -Process {
$a[$_..($_+$w-1)]
}
它将被展开。
那么你需要类似的东西:
0..($a.Length-$w) | ForEach-Object -Begin {
$myWindows = @()
} -Process {
$myWindows += @(,$a[$_..($_+$w-1)])
}
然后您可以使用:
$myWindows | ForEach-Object -Process {
"This is my window: $_"
}