user3014016
user3014016

Reputation: 75

Can Powershell Loop Through a Collection N objects at a time?

I am wondering how one would tackle looping through a collection of objects, processing the elements of that collection in groups instead of singularly, as is the case in normal Foreach loops. For example, instead of this:

$items = get-vm
foreach ($item in $items) { do something }

I would like to do this:

$items = get-vm
foreach ((5)$item in $items) {do something}

Essentially, this statement intends to say foreach 5 items in items do some work.....

Can anyone show me the proper constructs required to accomplish this?

Upvotes: 4

Views: 6672

Answers (4)

user3014016
user3014016

Reputation: 75

You guys definitely gave me some great ideas for this functionality. I ended up going with the following:

#create base collection
$group = get-vm
$i = 0

do {
    new-variable -Name "subgroup$i" -value $group[0..4]
    ++$i
    $group = $group[5..$group.length]
}
while ($group.length -gt 0)

This code results in a number of subgroups, which is based on how many times the base collection is divisible by 5, which is the desired subgroup quantity in this case......

Upvotes: 1

Mike Zboray
Mike Zboray

Reputation: 40788

Here's a function that will collection items into chunks of a specified size:

function ChunkBy($items,[int]$size) {
    $list = new-object System.Collections.ArrayList
    $tmpList = new-object System.Collections.ArrayList
    foreach($item in $items) {
        $tmpList.Add($item) | out-null
        if ($tmpList.Count -ge $size) {
            $list.Add($tmpList.ToArray()) | out-null
            $tmpList.Clear()
        }
    }

    if ($tmpList.Count -gt 0) {
        $list.Add($tmpList.ToArray()) | out-null
    }

    return $list.ToArray()
}

The usage would be something like:

ChunkBy (get-process) 10 | foreach { $_.Count }

Upvotes: 1

mjolinor
mjolinor

Reputation: 68243

I've got this:

 $array = 1..100
 $group = 10
 $i = 0

 do {
     $array[$i..(($i+= $group) - 1)]
     '*****'
     }
      until ($i -ge $array.count -1)

Upvotes: 6

user3012708
user3012708

Reputation: 946

Change to Do...Until, increment counter by 5 each time.

$items = get-vm
$i = 0
do {
#STUFF
$i = $i + 5
} until ($i -ge $items.count)

(Untested, but should give you an idea)

EDIT: Fully tested:

$items = @()
foreach ($item in (get-alias)) {
$items += $item
}

$i = 0
do {
write-host $i
$i = $i + 5
} until ($i -ge $items.count)

Output:

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135

EDIT 2:

$items = @()
for($i=1; $i -le 75; $i++) {
$items += $i
}

[int]$i = 0
$outarray = @()
do {
$outarray += $items[$i]
if ((($i+1)%5) -eq 0) {
    write-host $outarray
    write-host ---------
    $outarray = @()
}

$i = $i + 1
} until ($i -gt $items.count)

Upvotes: 0

Related Questions