ALI*_*ake 7 arrays indexing powershell
我无法获得完全相同对象的多个元素的当前元素的索引:
$b = "A","D","B","D","C","E","D","F"
$b | ? { $_ -contains "D" }
Run Code Online (Sandbox Code Playgroud)
替代版本:
$b = "A","D","B","D","C","E","D","F"
[Array]::FindAll($b, [Predicate[String]]{ $args[0] -contains "D" })
Run Code Online (Sandbox Code Playgroud)
这将返回:D D D.
但是这段代码:
$b | % { $b.IndexOf("D") }
Run Code Online (Sandbox Code Playgroud)
替代版本:
[Array]::FindAll($b, [Predicate[String]]{ $args[0] -contains "D" }) | % { $b.IndexOf($_) }
Run Code Online (Sandbox Code Playgroud)
返回:
1 1 1
所以它指向第一个元素的索引.如何获取其他元素的索引?
mjo*_*nor 10
你可以这样做:
$b = "A","D","B","D","C","E","D","F"
(0..($b.Count-1)) | where {$b[$_] -eq 'D'}
1
3
6
Run Code Online (Sandbox Code Playgroud)
mjolinor 的答案在概念上很优雅,但对于大数组来说很慢,大概是因为必须首先构建一个并行的索引数组(这也是内存效率低下的)。
它在概念上类似于以下基于 LINQ 的解决方案(PSv3+),其内存效率更高,速度大约是其两倍,但仍然很慢:
$arr = 'A','D','B','D','C','E','D','F'
[Linq.Enumerable]::Where(
[Linq.Enumerable]::Range(0, $arr.Length),
[Func[int, bool]] { param($i) $arr[$i] -eq 'D' }
)
Run Code Online (Sandbox Code Playgroud)
虽然与编译语言相比,任何PowerShell 循环解决方案最终都比较慢,但以下替代方案虽然更加冗长,但对于大型数组仍然要快得多:
PS C:\> & { param($arr, $val)
$i = 0
foreach ($el in $arr) { if ($el -eq $val) { $i } ++$i }
} ('A','D','B','D','C','E','D','F') 'D'
1
3
6
Run Code Online (Sandbox Code Playgroud)
笔记:
也许令人惊讶的是,这个解决方案甚至比Matt 的解决方案更快,后者[array]::IndexOf()
在循环中调用而不是枚举所有元素。
使用脚本块(使用调用运算符&
和参数调用)虽然不是绝对必要的,但用于防止辅助变量污染封闭范围$i
。
该foreach
语句比Foreach-Object
cmdlet更快(其内置别名是%
and,令人困惑的是,还有foreach
)。
$i
每个匹配项的简单(隐式)输出使 PowerShell 将多个结果收集到一个数组中。
[int]
实例;将整个命令包装起来@(...)
以确保您始终获得一个数组。虽然$i
它本身输出 的值$i
,++$i
但设计上不会(尽管(++$i)
如果需要,您可以使用它来实现)。
与 不同Array.IndexOf()
,PowerShell 的-eq
运算符默认不区分大小写;为了区分大小写,请-ceq
改用。
很容易把上面的变成一个(简单的)函数(注意参数是故意无类型的,为了灵活性):
function get-IndicesOf($Array, $Value) {
$i = 0
foreach ($el in $Array) {
if ($el -eq $Value) { $i }
++$i
}
}
Run Code Online (Sandbox Code Playgroud)
# Sample call
PS C:\> get-IndicesOf ('A','D','B','D','C','E','D','F') 'D'
1
3
6
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
18055 次 |
最近记录: |