PowerShell 有 "window" 函数吗?
Does PowerShell have a "window" function?
我一直在寻找 "window" 函数,例如 F# 的 Seq.windowed
或 Reactive 扩展 Window
。它看起来像是 Select-Object
之类的(已经具有 take / skip 功能)提供的,但事实并非如此。
如果没有现成的东西,有什么想法可以在没有不必要的程序循环的情况下实现 "window"?
我正在寻找可以很好地与 PowerShell 管道配合使用的东西。
据我所知没有这样的内置。 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)]
}
这确实处理了您想要的 window 数组。这样看更容易:
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: $_"
}
您会非常失望,因为 "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: $_"
}
您需要使用某种队列来累积和轮换足够的先前管道项:
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
我一直在寻找 "window" 函数,例如 F# 的 Seq.windowed
或 Reactive 扩展 Window
。它看起来像是 Select-Object
之类的(已经具有 take / skip 功能)提供的,但事实并非如此。
如果没有现成的东西,有什么想法可以在没有不必要的程序循环的情况下实现 "window"?
我正在寻找可以很好地与 PowerShell 管道配合使用的东西。
据我所知没有这样的内置。 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)]
}
这确实处理了您想要的 window 数组。这样看更容易:
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: $_"
}
您会非常失望,因为 "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: $_"
}
您需要使用某种队列来累积和轮换足够的先前管道项:
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