Reputation: 12047
I'm attempting to ensure an array of unknown length is split in one-or-more arrays with a maximum of 20 elements.
I've searched around and found several answers for similar questions based on arrays containing number sequences (or maybe I'm just missing something), but nothing for an array of strings.
I've come up with a solution, but it seems a little convoluted and I feel it could probably be better.
For example, take this array -
$metricDefinitionsHash= [ordered]@{"this one" = "111"; "that one" = "222"; "another one" = "333"}
And for the sake of this example, that's say I want only a maximum of two elements -
$metricsQueryParts = @()
$counter = 0
$metricDefinitionsHash.Keys | ForEach-Object {
$index = [System.Math]::Floor($counter / 2)
if ($metricsQueryParts.Length -eq $index)
{
$metricsQueryParts += ""
$metricsQueryParts[$index] = @()
}
$metricsQueryParts[$index] += $_
$counter++
}
So now I have an array of arrays -
@(@("this one", "that one"), @("another one"))
But... Can I achieve my goal in a more efficient way?
Upvotes: 1
Views: 1506
Reputation: 200213
Use a for
loop, the range operator (..
), and the unary array construction operator (,
):
[array]$keys = $metricDefinitionsHash.Keys
$size = 3
$metricsQueryParts = @()
for ($i=0; $i -lt $keys.Count; $i+=$size) {
$metricsQueryParts += ,$keys[$i..($i+$size-1)]
}
[array]$keys
casts the key/value collection .Keys
to a generic array (so that the index operator can be used on it).
The expression $i..($i+$size-1)
gives you the indexes from $i up to the index before $i+$size
, i.e. the next $size
elements from the array starting at position $i
. If there are less than $size
elements the expression will give just the remaining number of elements.
The unary array construction operator ensures that $keys[...]
is appended to $metricsQueryParts
as a nested array instead of just concatenating the two arrays.
Upvotes: 3
Reputation: 710
I really like Ansgar's solution but the keys collection isn't an array and as such you can't use the array range syntax. Keys is an OrderedDictionaryKeyValueCollection. I have used out-string -stream to force the OrderedDictionaryKeyValueCollection to an array.
$keys = $metricDefinitionsHash.Keys | out-string -stream
$size = 2
$metricsQueryParts = @()
for ($i=0; $i -lt $keys.Count; $i+=$size) {
$metricsQueryParts += ,$keys[$i..($i+$size-1)]
}
Upvotes: 1