What is the idiomatic way to slice an array relative to both of its ends?

前端 未结 7 1426
梦如初夏
梦如初夏 2021-02-06 20:35

Powershell\'s array notation has rather bizarre, albeit documented, behavior for slicing the end of arrays. This section from the official documentation sums up the bizarreness

相关标签:
7条回答
  • 2021-02-06 21:04

    I believe this is the right way to do it. all other methods require more code.

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

    Also, if array is converted to string it becomes easy to get data as below:

    $a = 0,1,2,3
    [string]::Concat($a).Substring(1)
    
    0 讨论(0)
  • 2021-02-06 21:09

    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

    0 讨论(0)
  • 2021-02-06 21:25

    $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)
    

    Actually code speaks for itself. I event don't need to explain.

    However, 1) Provide the first five elements, but each second of those five. Equal to arr[:5:2] in Python 2) Get the last five elements. 3) Gives unique elements 4) Firstly sort and then provide unique 5) Gives only elements which equal 0 by applying modulo of 5, sort, unique. 5) Provide the first count of elements in that array minus three elements only.

    0 讨论(0)
  • 2021-02-06 21:26

    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
    
    0 讨论(0)
  • 2021-02-06 21:26

    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.

    0 讨论(0)
  • 2021-02-06 21:27

    If you are looking for, say, the first three and last three elements in an array, with the results in an array, a little array addition will take care of the need.

    [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 ', '
    

    Yields:

    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
    
    0 讨论(0)
提交回复
热议问题