Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an array with large initial size in powershell

Tags:

powershell

The only way I know to create an array in powershell is

$arr = @(1, 2, 3)

However, this creating method is not convenient if I want to create an array with large initial size such as 10000.

Because I don't want to write code like this

$arr = @(0, 0, 0, 0, 0, 0, ... ,0) # 10000 0s in this line of code

Writing code like the following is not efficient.

$arr = @()
for ($i = 1; $i -le 10000; $i++) {
  $arr += 0
}

Because whenever += operator is executed, all of the elements in the old array would be copied into a newly created array.

What's the best way to create an array with large initial size in powershell?

like image 769
Brian Avatar asked Mar 29 '17 02:03

Brian


2 Answers

Array literal multiplication:

$arr = @($null) * 10000
like image 141
TessellatingHeckler Avatar answered Oct 30 '22 11:10

TessellatingHeckler


Use New-Object in this case:

PS> $arr = New-Object int[] 10000; $arr.length
10000

Or, in PSv5+, using the static new() method on the type:

PS> $arr = [int[]]::new(10000); $arr.length
10000

These commands create a strongly typed array, using base type [int] in this example. If the use case allows it, this is preferable for reasons of performance and type safety.

If you need to create an "untyped" array the same way that PowerShell does ([System.Object[]]), substitute object for int; e.g., [object[]]::new(10000); the elements of such an array will default to $null.
TessellatingHeckler's helpful answer, however, shows a much more concise alternative that even allows you initialize all elements to a specific value.


Arrays have a fixed size; if you need an array-like data structure that you can preallocate and grow dynamically, see Bluecakes' helpful [System.Collections.ArrayList]-based answer.

[System.Collections.ArrayList] is the resizable analog to [System.Object[]], and its generic equivalent - which like the [int[]] example above - allows you to use a specific type for performance and robustness (if feasible), is [System.Collections.Generic.List[<type>]], e.g.:

PS> $lst = [System.Collections.Generic.List[int]]::New(10000); $lst.Capacity
10000

Note that - as with [System.Collections.ArrayList] - specifying an initial capacity (10000, here) does not allocate the internally used array with that size right away - the capacity value is simply stored (and exposed as property .Capacity), and an internal array with that capacity (internal size that leaves room for growth) is allocated on demand, when the first element is added to the list.

[System.Collections.Generic.List[<type>]]'s .Add() method commendably does not produce output, whereas [System.Collections.ArrayList]'s does (it returns the index of the element that was just added).

# The non-generic ArrayList's .Add() produces (usually undesired) output.
PS> $al = [System.Collections.ArrayList]::new(); $al.Add('first elem')
0  # .Add() outputs the index of the newly added item

# Simplest way to suppress this output:
PS> $null = $al.Add('first elem')
# NO output.

# The generic List[T]'s .Add() does NOT produce output.
PS> $gl = [System.Collections.Generic.List[string]]::new(); $gl.Add('first elem')
# NO output from .Add()
like image 33
mklement0 Avatar answered Oct 30 '22 11:10

mklement0