27

How can I get the array element range of first to second last?

For example,

$array = 1,2,3,4,5
$array[0] - will give me the first (1)
$array[-2] - will give me the second last (4)
$array[0..2] - will give me first to third (1,2,3)
$array[0..-2] - I'm expecting to get first to second last (1,2,3,4) but I get 1,5,4 ???

I know I can do long hand and go for($x=0;$x -lt $array.count;$x++), but I was looking for the square bracket shortcut.

3
  • 7
    You could just do $array[0..($array.length-2)]. Commented May 1, 2014 at 0:52
  • Robert's suggestion is unfortunately the best way I know of. I too wanted $array[0..-2] to behave as you expected it to. But no, it indexes backwards 0 -> [len-1] -> [len - 2]. I really don't see how that is useful at all. Commented May 1, 2014 at 0:59
  • @robert.westerlund You should add your comment as an answer so we can close this question :) Commented May 1, 2014 at 16:33

4 Answers 4

31

You just need to calculate the end index, like so:

$array[0..($array.length - 2)]

Do remember to check that you actually have more than two entries in your array first, otherwise you'll find yourself getting duplicates in the result.

An example of such a duplicate would be:

@(1)[0..-1]

Which, from an array of a single 1 gives the following output

1 
1
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this! It's a shame though that you can use negative indexing but it is not implemented in ranges; it is unnatural and frustrating.
[1,2,3,4][1..-1] in Ruby results in [2,3,4]. @(1,2,3,4)[1..-1] in Powershell results in 2,1,4. The issue with -1 in Powershell is not only about duplicates.
13

There might be a situation where you are processing a list, but you don't know the length. Select-object has a -skiplast parameter.

(1,2,3,4,5 | select -skiplast 2)

1
2
3

Comments

7

As mentioned earlier the best solution here: $array[0..($array.length - 2)]

The problem you met with $array[0..-2] can be explained with the nature of "0..-2" expression and the range operator ".." in PowerShell. If you try to evaluate just this part "0..-2" in PowerShell you will see that result will be an array of numbers from 0 to -2.

>> 0..-2
0
-1
-2

And when you're trying to do $array[0..-2] in PowerShell it's the same as if you would do $array[0,-1,-2]. That's why you get results as 1, 5, 4 instead of 1, 2, 3, 4.

It could be kind of counterintuitive at first especially if you have some Python or Ruby background, but you need to take it into account when using PowerShell.

Comments

3

Robert Westerlund answer is excellent. This answer I just saw on the Everything you wanted to know about arrays page and wanted to try it out. I like it because it seems to describe exactly what the goal is, end at one short of the upper bound.

$array[0..($array.GetUpperBound(0) - 1)]
1
2
3
4

I used this variation of your original attempt to uninstall all but the latest version from Get-InstalledModule. It's really short, but not perfect because if there are more than 9 items it still returns just 8, but you can put a larger negative number, though.

$array[-9..-2]
1
2
3
4

1 Comment

I had no idea .GetUpperBound(0) existed. .GetUpperBound(0) - 1 is so much more intuitive than .Count - 2, even if it is longer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.