2012-12-15 56 views
2

例如,给定列表1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8和数字4,它返回长度为4的列表的列表,即 (1, 2, 3, 4), (5, 6, 7, 8), (1, 2, 3, 4), (5, 6, 7, 8)Powershell将一个长阵列分成长度为N的数组在一行中?

基本上我想在Powershell中实现下面的Python代码。

s = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8 
z = zip(*[iter(s)]*4) # Here N is 4 
# z is (1, 2, 3, 4), (5, 6, 7, 8), (1, 2, 3, 4), (5, 6, 7, 8) 

以下脚本返回的17代替5.

$a = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,0 
$b = 0..($a.Length/4) | % { @($a[($_*4)..($_*4 + 4 - 1)]) } 
$b.Length 
+0

很好的解决方案。你将如何处理N个不能被N整除的元素?在这种情况下是4。 $ a = 1..18 –

+0

@DougFinke创建一个变量'$ n = 4',并用'$ n'替换所有的4s应该可以工作。 – ca9163d9

+0

同意。我想我问的是。当你有一组不可被N整除的数组时,你如何处理左边的边界? –

回答

5
PS> $a = 1..16 
PS> $z=for($i=0; $i -lt $a.length; $i+=4){ ,($a[$i]..$a[$i+3])} 
PS> $z.count 
4  

PS> $z[0] 
1 
2 
3 
4 

PS> $z[1] 
5 
6 
7 
8 

PS> $z[2] 
9 
10 
11 
12 

PS> $z[3] 
13 
14 
15 
16 
+1

接受的解决方案仅适用于连续整数。 例如,当$ i是0时,$ a [$ i]是1,$ a [$ i + 3]是4,因此1 .. 4将起作用。但正确的解决方案是 '$ z = for($ i = 0; $ i -lt $ a.length; $ i + = 4){,($ a [$ i ..($ i + 3)]) }' –

6

写到这在2009年PowerShell Split-Every Function

大概可以得到改善。

Function Split-Every($list, $count=4) { 
    $aggregateList = @() 

    $blocks = [Math]::Floor($list.Count/$count) 
    $leftOver = $list.Count % $count 
    for($i=0; $i -lt $blocks; $i++) { 
     $end = $count * ($i + 1) - 1 

     $aggregateList += @(,$list[$start..$end]) 
     $start = $end + 1 
    }  
    if($leftOver -gt 0) { 
     $aggregateList += @(,$list[$start..($end+$leftOver)]) 
    } 

    $aggregateList  
} 

$s = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8 

$r = Split-Every $s 4 

$r[0] 
"" 
$r[1] 
"" 
$r[2] 
"" 
$r[3] 
+0

如果列表的长度是<$ count,那么$ startList和$ end将在未初始化的$ aggregateList代码中使用(或设置为未知值)。 修正是在for循环上面添加$ start = $ end = 0。 – lovedatsnow

1
$a = 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,0 
$b = 0..([Math]::ceiling($a.Length/4) - 1) | 
    % { @(, $a[($_*4)..($_*4 + 4 - 1)]) } 

不知道为什么,我不得不把一个逗号(后。

1

清除,主机

$ S = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 ,18

$计数= $ s.Length

$分裂= $计数/ 2

$分裂 -

$ b $ = S [0 .. $分裂]

$分裂++

$ a = $ S [$分裂.. $计数]

写主机 “第一阵列”

$ B

写主机“下一个阵”

$一个

清理

获取变量 - 排除PWD,*偏好|删除 - 变量-EA 0

+1

您能否在此答案中添加更多详细信息?这只是代码而已,所以有点解释会很好 – KhorneHoly

11

这有点旧,但我想我会抛出我用于将数组拆分为块的方法。您可以使用组,对象与构造属性:

$bigList = 1..1000 

$counter = [pscustomobject] @{ Value = 0 } 
$groupSize = 100 

$groups = $bigList | Group-Object -Property { [math]::Floor($counter.Value++/$groupSize) } 

$groups会的GroupInfo对象的集合;在这种情况下,每个组将具有100个元素(可通过$groups[0].Group$groups[1].Group等访问)。我使用计数器的对象属性来避免-Property脚本块内的作用域问题,因为简单的$i++不会写入回到原来的变量。或者,您可以使用$script:counter = 0$script:counter++,并获得没有自定义对象的相同效果。

+0

这是美的事情,谢谢! – Froosh

+0

我想使用这个,但我需要先由一个附加属性进行分组。每当'baseomain'属性更改时,我怎样才能让'$ counter'重置? –

+0

明白了:看我的答案http://serverfault.com/a/823936/190386 –

1

@Shay Levy答案:如果您将a的值更改为1 ..15那么你的解决方案不工作了(彼得Reavy评论)

所以这个工作对我来说:

$a = 1..15 
$z=for($i=0; $i -lt $a.length; $i+=4){if ($a.length -gt ($i+3)) { ,($a[$i]..$a[$i+3])} else { ,($a[$i]..$a[-1])}} 
$z.count