What is the idiomatic way to slice an array relative to both of its ends?
If you want to get n elements from the end of an array simply fetch the elements from -n to -1:
PS C:\> $a = 0,1,2,3 PS C:\> $n = 2 PS C:\> $a[-$n..-1] 2 3
Edit: PowerShell doesn't support indexing relative to both beginning and end of the array, because of the way $a[$i..$j]
works. In a Python expression a[i:j]
you specify i
and j
as the first and last index respectively. However, in a PowerShell ..
is the range operator, which generates a sequence of numbers. In an expression $a[$i..$j]
the interpreter first evaluates $i..$j
to a list of integers, and then the list is used to retrieve the array elements on these indexes:
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
If you need to emulate Python's behavior, you must use a subexpression:
PS C:\> $a = 0,1,2,3 PS C:\> $i = 1; $j = -1 PS C:\> $a[$i..($a.Length+$j-1)] 1 2
Combine Select-Object -Skip
and Select-Object -SkipLast
like:
$a = 0,1,2,3
$a | Select-Object -Skip 1 | Select-Object -SkipLast 1
Returns:
1
2
Not as elegant as Python, but at least you don't have to use Count
or Length
, meaning this also works if the array isn't stored in a variable.
Although not as neat as you might want but is cleaner in the way PowerShell works ...
(@(1,2,3,4)) | Select-Object -Skip 1
returns ...
2
3
4
This could be the most idiomatic way to slice an array with both of its ends:
$array[start..stop] where stop is defined by taking the length of the array minus a value to offset from the end of the array:
$a = 1,2,3,4,5,6,7,8,9
$start = 2
$stop = $a.Length-3
$a[$start..$stop]
This will return 3 4 5 6 7
The start value starts counting with zero, so a start value of '2' gives you the third element of the array. The stop value is calculated with ($a.Length-3), this will drop the last two values because $a.Length-3 itself is included in the slice.
I have defined $start and $stop for clarity, obviously you can also write it like this:
$a = 1,2,3,4,5,6,7,8,9
$a[2..($a.Length-3)]
This will also return 3 4 5 6 7