将PowerShell数组切割为较小数组的组

时间:2017-08-29 21:28:30

标签: arrays powershell data-partitioning

我想基于变量将单个数组转换为一组较小的数组。因此,0,1,2,3,4,5,6,7,8,9在大小为3时会变为0,1,23,4,56,7,89

我目前的做法:

$ids=@(0,1,2,3,4,5,6,7,8,9)
$size=3

0..[math]::Round($ids.count/$size) | % { 

    # slice first elements
    $x = $ids[0..($size-1)]

    # redefine array w/ remaining values
    $ids = $ids[$size..$ids.Length]

    # return elements (as an array, which isn't happening)
    $x

} | % { "IDS: $($_ -Join ",")" }

产地:

IDS: 0
IDS: 1
IDS: 2
IDS: 3
IDS: 4
IDS: 5
IDS: 6
IDS: 7
IDS: 8
IDS: 9

我希望它是:

IDS: 0,1,2
IDS: 3,4,5
IDS: 6,7,8
IDS: 9

我错过了什么?

5 个答案:

答案 0 :(得分:4)

为了完整起见:

var x = "subdomain.domain.com/username?something-9732422348-2"
x=x.split("?")
x.splice(0,1)
console.log(x) //["something-9732422348-2"]

用法:

function Slice-Array
{

    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$True)]
        [String[]]$Item,
        [int]$Size=10
    )
    BEGIN { $Items=@()}
    PROCESS {
        foreach ($i in $Item ) { $Items += $i }
    }
    END {
        0..[math]::Floor($Items.count/$Size) | ForEach-Object { 
            $x, $Items = $Items[0..($Size-1)], $Items[$Size..$Items.Length]; ,$x
        } 
    }
}

答案 1 :(得分:3)

您可以使用class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( floatingActionButton: new Builder( builder: (BuildContext context) { return new FloatingActionButton( onPressed: () { Scaffold.of(context).showSnackBar(new SnackBar( content: new Text("Sending Message"), )); }, tooltip: 'Increment', child: new Icon(Icons.add), ); } ), ); } } 代替,$x

文档中的$x部分包含:

about_Operators

答案 2 :(得分:2)

cls
$ids=@(0,1,2,3,4,5,6,7,8,9)
$size=3

<# 
Manual Selection:
    $ids | Select-Object -First 3 -Skip 0
    $ids | Select-Object -First 3 -Skip 3
    $ids | Select-Object -First 3 -Skip 6
    $ids | Select-Object -First 3 -Skip 9
#>

# Select via looping
$idx = 0
while ($($size * $idx) -lt $ids.Length){

    $group = $ids | Select-Object -First $size -skip ($size * $idx)
    $group -join ","
    $idx ++
} 

答案 3 :(得分:1)

要将说明添加到Bill Stewart's effective solution

隐式输出 或使用return输出诸如数组 [1] 之类的集合,都会单独发送其元素 通过pipeline ;也就是说,集合是枚举的 (已展开):

# Count objects received.
PS> (1..3  | Measure-Object).Count
3   # Array elements were sent *individually* through the pipeline.

使用, (comma; the array-construction operator)的一元形式来防止枚举是一种简便的方法,尽管解决方法有点晦涩:

PS> (, (1..3) | Measure-Object).Count 
1   # By wrapping the array in a helper array, the original array was preserved.

也就是说,, <collection>在原始集合周围创建了一个瞬态的单元素辅助数组,因此枚举仅应用于该辅助数组,将封闭的原始集合作为单个对象原样输出。< / p>

从概念上讲更清晰,但更冗长和更慢的方法是使用Write-Output -NoEnumerate ,它明确表明了将集合作为输出的意图。单个对象

PS> (Write-Output -NoEnumerate (1..3) | Measure-Object).Count 
1   # Write-Output -NoEnumerate prevented enumeration.

目视检查有关的陷阱:

在输出用于显示时,似乎会再次擦除多个数组之间的边界:

PS> (1..2), (3..4) # Output two arrays without enumeration
1
2
3
4

也就是说,即使每个2个2元素数组都作为一个对象发送,通过显示每行中的元素,输出看起来像是接收到一个平面4元素数组。

一种简单的解决方法是对每个数组进行 stringify ,这会将每个数组转换为包含以空格分隔的元素列表的字符串。

PS> (1..2), (3..4) | ForEach-Object { "$_" }
1 2
3 4

现在很明显收到了两个单独的数组。


[1] 枚举哪些数据类型
自动枚举实现IEnumerable接口的数据类型的实例,但是有例外:
还实现IDictionary的类型(例如 hashtables ),不会枚举 ,也不会是XmlNode实例。
相反,列举了DataTable(未实现IEnumerable 的实例(作为其.Rows集合的元素)-请参见{{3} }
此外,请注意,外部程序的stdout输出逐行列举

答案 4 :(得分:0)

克雷格(Craig)自己方便地将拆分(分区)功能包装在 robust function 中:

让我提供它的性能更好的改进(PSv3 +语法,重命名为Split-Array),

  • 使用可扩展的System.Collections.Generic.List[object]]集合更有效地收集输入对象。

  • 在拆分过程中不会修改集合,而是从其中提取元素的范围

function Split-Array {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [String[]] $InputObject
        ,
        [ValidateRange(1, [int]::MaxValue)]
        [int] $Size = 10
    )
    begin   { $items = New-Object System.Collections.Generic.List[object] }
    process { $items.AddRange($InputObject) }
    end {
      $chunkCount = [Math]::Floor($items.Count / $Size)
      foreach ($chunkNdx in 0..($chunkCount-1)) {
        , $items.GetRange($chunkNdx * $Size, $Size).ToArray()
      }
      if ($chunkCount * $Size -lt $items.Count) {
        , $items.GetRange($chunkCount * $Size, $items.Count - $chunkCount * $Size).ToArray()
      }
    }
}

使用较小的输入集合,优化不会有多大作用,但是一旦您了解了成千上万个元素,加速就会非常惊人:

使用Time-Command粗略了解性能改进:

$ids = 0..1e4 # 10,000 numbers
$size = 3 # chunk size

Time-Command { $ids | Split-Array -size $size }, # optimized
             { $ids | Slice-Array -size $size }  # original

具有Windows 5.1的单核Windows 10 VM的采样结果(绝对时间并不重要,但是因素是)

Command                        Secs (10-run avg.) TimeSpan         Factor
-------                        ------------------ --------         ------
$ids | Split-Array -size $size 0.150              00:00:00.1498207 1.00
$ids | Slice-Array -size $size 10.382             00:00:10.3820590 69.30

请注意,未优化的功能的运行速度几乎降低了70倍。