fin_anorak
fin_anorak

Reputation: 11

How to use a 2D array in powershell?

I have a powershell script where I group and store a collection of Conputernames in a hashtable. Everithing works fine so far.

    $table = @{}
    $pcs = "w7cl002","w7cl002","w7cl001","w7cl002","w7cl008", `
           "w7lp001","w7lp001","w7cl008","w7cl004","w7lp001"



    foreach ($pc in $pcs){

        if ($table.Keys -notcontains $pc){

            $Table.Add($pc,1)
        }

        else{

            $occ = $table.get_item($pc) +1
            $table.set_item($pc,$occ)
        }
    }
    $table

This is what I want and what I get.

    Name                           Value                                                                                                                                                                                                                                                            
    ----                           -----                                                                                                                                                                                                                                                            
    stflw7lp001                    3                                                                                                                                                                                                                                                                
    stflw7cl002                    3                                                                                                                                                                                                                                                                
    stflw7cl004                    1                                                                                                                                                                                                                                                                
    stflw7cl001                    1                                                                                                                                                                                                                                                                
    stflw7cl008                    2 

Initially, I wanted to do this by using a 2D-Array. But after 5 hours struggling and running my head against a wall, I gave up and realized it with a hash table.

I just would be interested in whether this is possible using a 2D array?

Upvotes: 1

Views: 640

Answers (2)

Joey
Joey

Reputation: 354794

2D arrays (in the C# sense, not the Java sense) are icky in PowerShell. I tend to avoid them. There is no direct language support for them either, and you have to create them with New-Object.

As for your code, you can achieve the same with this:

$pcs = "w7cl002","w7cl002","w7cl001","w7cl002","w7cl008",
       "w7lp001","w7lp001","w7cl008","w7cl004","w7lp001"

$table = @{}
$pcs | Group-Object -NoElement | ForEach-Object { $table[$_.Name] = $_.Count }

No need for awkward loops and code that looks like an unholy combination of C# and VBScript (honestly, none of the actual working lines in your code look like PowerShell, except for the first three and the last).

If you need arrays of arrays instead of a hashtable, you can do so as well:

$result = $pcs | Group-Object -NoElement | ForEach-Object { ,($_.Name, $_.Count) }

However, you really don't want to work this way. For one, you can often get confused whether you have an array or a scalar as an item. Some operations may automatically unroll the array again, etc. IMHO it's much better to work with objects when you can. In this case, just use the result from Group-Object directly. It has handy Name and Count properties that spell out exactly what they are, instead of [0] and [1] which are a bit more opaque.

If you need nicer property names, just project into new objects:

$pcs | group -n | % {
    New-Object PSObject -Property @{
        PC = $_.Name
        Count = $_.Count
    }
}

or

$pcs | group -n | select @{l='PC';e={$_.Name}},Count

Generally, when using PowerShell, think of your data as objects and your problem as operations on those objects. Then try to find how to make those operations happen with things the language already gives you. Manipulation of collection classes, or C-like code with lots of loops almost always looks out of place and wrong in PowerShell – usually for good reason, because the pipeline is often a better, easier, and shorter way of accomplishing the same. I can probably count the number of times I used a for loop in PowerShell over the past few years on both hands, while I wouldn't need both hands to count the number of times I used a foreach loop. Those are rare things to use.

Upvotes: 3

Walter Mitty
Walter Mitty

Reputation: 18940

In general, what I end up with in a situation like this is not a 2D array, but an array of tuples, or an array of custom objects. This is what import-csv gives you by default. For my work, this is a good representation of a relation, and many of the transforms I want are some combination of set ops and relational ops.

BTW, I'm only a beginner in Powershell.

Upvotes: 0

Related Questions