将数组相对于两端切割的惯用方法是什么?

时间:2015-02-11 17:07:02

标签: arrays powershell idioms

Powershell的数组符号在切片数组末尾时有相当奇怪的行为,尽管有记录。 the official documentation的这一部分很好地总结了奇异性:

  

负数从数组末尾开始计算。例如," -1"   指的是数组的最后一个元素。显示最后三个   数组的元素,键入:

$a[-3..-1]
     

但是,使用此表示法时要小心。

$a[0..-2]
     

此命令不引用数组的所有元素,除外   为了最后一个。它指的是第一个,最后一个,倒数第二个   数组中的元素。

以下代码证实了这一奇异性:

$a = 0,1,2,3
$a[1..-1]

确实输出了这个奇怪的结果:

1
0
3

所以,问题是,用一个索引相对于开始切片而另一个相对于数组末尾的惯用方法是什么?

请告诉我它比这个丑陋的混乱更好:

$a[1..($a.Count-1)]

编辑:

另一种描述我正在寻找的东西的方法是:这个python表达式的惯用Powershell等价物:

a=1,2,3,4
a[1:-1]

当然,评估为(2,3)

8 个答案:

答案 0 :(得分:30)

如果您想从数组末尾获取 n 元素,只需将 -n 中的元素提取到 -1

PS C:\> $a = 0,1,2,3
PS C:\> $n = 2
PS C:\> $a[-$n..-1]
2
3

编辑:PowerShell不支持相对于数组的起始结尾的索引,因为$a[$i..$j]的工作方式。在Python表达式a[i:j]中,您分别指定ij作为第一个和最后一个索引。但是,在PowerShell中..range operator,它会生成一系列数字。在表达式$a[$i..$j]中,解释器首先将$i..$j计算为整数列表,然后使用该列表检索这些索引上的数组元素:

PS C:\> $a = 0,1,2,3
PS C:\> $i = 1; $j = -1
PS C:\> $index = $i..$j
PS C:\> $index
1
0
-1
PS C:\> $a[$index]
1
0
3

如果你需要模仿Python的行为,你必须使用子表达式:

PS C:\> $a = 0,1,2,3
PS C:\> $i = 1; $j = -1
PS C:\> $a[$i..($a.Length+$j-1)]
1
2

答案 1 :(得分:7)

虽然不像你想要的那样整洁但是PowerShell工作方式更清晰......

(@(1,2,3,4)) | Select-Object -Skip 1

返回......

2
3
4

答案 2 :(得分:2)

如果您正在寻找数组中的前三个和后三个元素,并将结果放在一个数组中,那么添加一个小数组就可以满足需要。

[array]$A = (([int][char]'A')..([int][char]'Z')) | ForEach-Object {[char]$_}
$B = $A[0..2]+$A[-3..-1]
Clear-Host
Write-Host "Original List"
Write-Host $A -NoNewline -Separator ', '
Write-Host
Write-Host "First three and last three"
Write-Host $B -NoNewline -Separator ', '

收率:

Original List
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
First three and last three
A, B, C, X, Y, Z

答案 3 :(得分:2)

这可能是用两种方式对数组进行切片的最惯用的方式:

$ array [start..stop]其中stop是通过将数组的长度减去一个从数组末尾偏移的值来定义的:

$a = 1,2,3,4,5,6,7,8,9
$start = 2
$stop = $a.Length-3
$a[$start..$stop]

这将返回 3 4 5 6 7

起始值从零开始计数,因此起始值为' 2'为您提供数组的第三个元素。停止值用($ a.Length-3)计算,这将删除最后两个值,因为$ a.Length-3本身包含在切片中。

为了清晰起见,我定义了$ start和$ stop,显然你也可以这样写:

$a = 1,2,3,4,5,6,7,8,9
$a[2..($a.Length-3)]

这也将返回3 4 5 6 7

答案 4 :(得分:2)

像这样组合Select-Object -SkipSelect-Object -SkipLast

$a = 0,1,2,3
$a | Select-Object -Skip 1 | Select-Object -SkipLast 1

返回:

1
2

不如Python优雅,但是至少您不必使用CountLength,这意味着如果数组未存储在变量中,这也可以使用。

答案 5 :(得分:1)

好吧,所以它很难看,但我发现[1..99]或[1..999]有效。但是,不要使用[1..999999],因为PowerShell在决定只有前五个问题之前首先生成一个值数组,最后一个需要花费大量时间来预先生成一个百万元素数组。

这对某些脚本编写方案很有用,对于生产代码来说很糟糕。

答案 6 :(得分:0)

我认为这是正确的做法。所有其他方法都需要更多代码。

$a[1..($a.Count-1)]

此外,如果将数组转换为字符串,则可以轻松获取如下数据:

$a = 0,1,2,3
[string]::Concat($a).Substring(1)

答案 7 :(得分:0)

$ arr = @(10、1、2、3、4、5、6、7、8、9、10)

$arr | Select-Object -First 5 | Select-Object -Index (@(0..4) | Where-Object { $_ % 2 -eq 0}) 
$arr | Select-Object -Last 5
$arr | Select-Object -Unique
$arr | Sort-Object | Select-Object -Unique
$arr | Where-Object {  $_ % 5 -eq 0 } | Sort-Object | Select-Object -Unique
$arr | Select-Object -First ($arr.Count - 3)

实际上,代码可以说明一切。 我事件不需要解释。

但是, 1)提供前五个元素,但提供这五个元素的第二个元素。在Python中等于arr [:5:2] 2)获取最后五个元素。 3)赋予独特的元素 4)首先排序,然后提供唯一 5)通过应用5的模,排序,唯一性,仅给出等于0的元素。 5)提供该数组中的第一个元素数减去三个元素。