对数组中的项目进行分组

时间:2014-02-12 00:12:03

标签: arrays powershell split

鉴于此数组:

@("abc", 5, 4, 2, 7, 6, 5, 4, "abc", 7, 9, 3, "abc", 3, 2, 4)

我想最终得到一个阵列数组:

@("abc", 5, 4, 2, 7, 6, 5, 4)
@("abc", 7, 9, 3)
@("abc", 3, 2, 4)

即。将原始数组拆分为多个组,每个组包括“abc”以及跟随它到下一个“abc”或数组末尾的项目。

这是一种方法:

$result = @("abc", 5, 4, 2, 7, 6, 5, 4, "abc", 7, 9, 3, "abc", 3, 2, 4)

$arrs = @()

$arr = @()

$result | ForEach-Object {
    if ($_ -eq 'abc') 
    { 
        if ($arr.Count -gt 0) { $arrs += , $arr }
        $arr = @() 
    }
    $arr += $_
}

$arrs += , $arr

PowerShell中有更惯用的方法吗?

3 个答案:

答案 0 :(得分:2)

这是另一种方法:

$r = @("abc", 5, 4, 2, 7, 6, 5, 4, "abc", 7, 9, 3, "abc", 3, 2, 4) | 
       Foreach -Begin {$arr=$null} -Process {if ($_ -eq 'abc') {,$arr; $arr = @('abc')} else {$arr += @($_)}} -End {,$arr} | 
       Where {$_}
$r[0]

输出:

abc
5
4
2
7
6
5
4

答案 1 :(得分:1)

嗯,有一种稍微更具风格的方法,但它涉及多次连接和分割数组和字符串,这可能会对性能产生负面影响,并且肯定更难以阅读。

$result = @("abc", 5, 4, 2, 7, 6, 5, 4, "abc", 7, 9, 3, "abc", 3, 2, 4)
$arrays = $result -join "," -split "abc" | ? { $_ } | % {,($_ -split ",")}

只有当您的数据点永远不会偏离"abc",1,2,3格式时才会有效。

我们首先用逗号连接整个数组,然后在文本分隔符上拆分,然后丢弃任何空结果。如果我们不丢弃,拆分将根据拆分时有n + 1个拆分数组的事实给你一个空数组,即使它找到的第一个项是拆分字符串。

现在我们有n个字符串代表我们的数据集。循环遍历这些,将它们分开在逗号上以获取您的各个数组。对于您提供的示例集,此代码段将给出:

@(5,4,2,7,6,5,4)
@(7,9,3)
@(3,2,4)

现在,如果您希望文本分隔符位于数组的开头,请将命令更改为:

    $arrays = $result -join "," -split "abc" | ? { $_ } | % {,("abc" + $_ -split ",")}

您的里程可能会有所不同,因为我仅在PowerShell 4上对此进行了测试,但我不记得-split-join运算符的性能在以前的版本中有所不同。

答案 2 :(得分:0)

在示例中,"abc"可以被视为分隔符。示例中的分组发生使得分隔符包含在组的 left 中。这里的函数更为通用,因为它接受用于查找分隔符的谓词:

function Split-Array-Pred-Left ()
{
    param($in, $pred)

    $arrs = @()

    $arr = @()

    $in | ForEach-Object {
        if (& $pred $_) { $arrs += , $arr; $arr = @(); }
        $arr += $_
    }

    $arrs += , $arr

    $arrs
}

一个类似的函数,包括每个组的 right 的分隔符是相同的,但有两行交换:

function Split-Array-Pred-Right ()
{
    param($in, $pred)

    $arrs = @()

    $arr = @()

    $in | ForEach-Object {
        $arr += $_
        if (& $pred $_) { $arrs += , $arr; $arr = @(); }
    }

    $arrs += , $arr

    $arrs
}

示例:

PS C:\Users\dharmatech> $result = @(4, "abc", 1, 7, 5, "abc", 7, 2, 5, 4, "abc", 8, 7)

PS C:\Users\dharmatech> Split-Array-Pred-Left $result { param($elt) $elt -like 'abc' } | ForEach-Object { $_; '' }
4

abc
1
7
5

abc
7
2
5
4

abc
8
7


PS C:\Users\dharmatech> Split-Array-Pred-Right $result { param($elt) $elt -like 'abc' } | ForEach-Object { $_; '' }
4
abc

1
7
5
abc

7
2
5
4
abc

8
7