1

I am trying to create an array of HashSets but it always comes out as simply a HashSet. Here is a test script I made:

$arrHashSets = @();

$hs = New-Object System.Collections.Generic.HashSet[string];
$hs2 = New-Object System.Collections.Generic.HashSet[string];

$hs.Add("A");
$hs.Add("B");
$hs.Add("C");

$hs2.Add("A");
$hs2.Add("B");
$hs2.Add("C");

$arrHashSets += $hs;
$arrHashSets += $hs2;

Expected result:

$arrHashSets = [
    {"A", "B", "C"},
    {"A", "B", "C"}
]

Actual result:

$arrHashSets = {"A", "B", "C"}

I tried doing it a few different ways but $arrHashSets always comes out as simply a HashSet rather than an array of type HashSet. What am I doing wrong?

SendETHToThisAddress
  • 2,756
  • 7
  • 29
  • 54

1 Answers1

3

Replace:

$arrHashSets += $hs
$arrHashSets += $hs2

with:

$arrHashSets = $hs, $hs2

If you do need to build up an array(-like data structure) iteratively:

$lstHashSets = [System.Collections.Generic.List[object]]::new()
foreach ($thisHs in $hs, $hs2) {
  $lstHashSets.Add($thisHs)
}

Note: For simplicity the generic list is [object]-typed here, but you could more strictly type it as [System.Collections.Generic.List[System.Collections.Generic.HashSet[string]]].

However, creating an array / list explicitly isn't strictly needed, given that you can use a statement such as foreach loop as an expression whose multiple outputs PowerShell implicitly captures in an array for you:

$arrHashSets = @(
  foreach ($thisHs in $hs, $hs2) {
    , $thisHs
  }
)

Note:

  • @(...), the array-subexpression operator is necessary to ensure that an array is also constructed in the event that the foreach loop happens to output only a single object.

  • The unary form of ,, the array constructor operator is used to in effect ensure that each hash set is output as a whole. By default, PowerShell would enumerate the hash set's entries, i.e. output them one by one - see this answer for more information.


As for what you tried:

Using += to "extend" an array:

  • is generally to be avoided due to its inefficiency: a new array must be created behind the scenes every time - see this answer.

  • "adds" to the existing array by appending the elements of the RHS, if it is an enumerable, rather than appending the RHS as a whole. Thus, the hash set is enumerated and its elements become direct elements of the resulting, flat array.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thanks mklement0! I found that your first suggestion didn't make a difference, but using a List instead of an array worked, along with using `.Add()` instead of `+=`. – SendETHToThisAddress Sep 28 '22 at 22:37
  • Glad to hear it, @SendETHToThisAddress, though the first suggestion should work as well; try this simplified command: `$arr = [System.Collections.Generic.HashSet[string]] ('A', 'B', 'C'), [System.Collections.Generic.HashSet[string]] ('D', 'E', 'F')` – mklement0 Sep 28 '22 at 22:42
  • @SendETHToThisAddress, I corrected a problem in my answer where I inadvertently used `$hs` as the _iteration_ variable as well. – mklement0 Sep 28 '22 at 22:45