web-dev-qa-db-ja.com

PSObject、Hashtable、PSCustomObjectの違い

誰でも詳細を説明できますか?を使用してオブジェクトを作成する場合

_$var = [PSObject]@{a=1;b=2;c=3}
_

そして、getType()を使用してそのタイプを探しますPowerShellは、タイプHashtableであることを教えてくれます。

Get-Member (別名gm)を使用してオブジェクトを検査する場合、keysvaluesプロパティ。それでは、「通常の」ハッシュテーブルとの違いは何ですか?

また、PSCustomObjectを使用する利点は何ですか?このようなものを使用して作成する場合

_$var = [PSCustomObject]@{a=1;b=2;c=3}
_

私に見える唯一の違いは、PSCustomObjectの異なるデータ型です。また、キーと値のプロパティの代わりに、gmを使用した検査は、すべてのキーがNotePropertyオブジェクトとして追加されたことを示しています。

しかし、私にはどんな利点がありますか?ハッシュテーブルと同じように、キーを使用して値にアクセスできます。単純なキーと値のペア(たとえば、キーとオブジェクトのペア)以上のものを、ハッシュテーブルと同様にPSCustomObjectに格納できます。それで、利点は何ですか?重要な違いはありますか?

27
masi

あなたが見る最大の違いはパフォーマンスだと思います。このブログ投稿をご覧ください。

オブジェクトの効率的な結合-ハッシュテーブルを使用してオブジェクトのコレクションにインデックスを付ける

著者は次のコードを実行しました。

$numberofobjects = 1000

$objects = (0..$numberofobjects) |% {
    New-Object psobject -Property @{'Name'="object$_";'Path'="Path$_"}
}
$lookupobjects = (0..$numberofobjects) | % {
    New-Object psobject -Property @{'Path'="Path$_";'Share'="Share$_"}
}

$method1 = {
    foreach ($object in $objects) {
        $object | Add-Member NoteProperty -Name Share -Value ($lookupobjects | ?{$_.Path -eq $object.Path} | select -First 1 -ExpandProperty share)
    }
}
Measure-Command $method1 | select totalseconds

$objects = (0..$numberofobjects) | % {
    New-Object psobject -Property @{'Name'="object$_";'Path'="Path$_"}
}
$lookupobjects = (0..$numberofobjects) | % {
    New-Object psobject -Property @{'Path'="Path$_";'Share'="Share$_"}
}

$method2 = {
    $hash = @{}
    foreach ($obj in $lookupobjects) {
        $hash.($obj.Path) = $obj.share
    }
    foreach ($object in $objects) {
        $object |Add-Member NoteProperty -Name Share -Value ($hash.($object.path)).share
    }
}
Measure-Command $method2 | select totalseconds

<#
Blog author's output:

TotalSeconds
------------
 167.8825285
   0.7459279
#>

コード結果に関する彼のコメントは次のとおりです。

速度をすべて合わせると、速度の違いがわかります。私のコンピューターではオブジェクトメソッドは167秒かかりますが、ハッシュテーブルメソッドはハッシュテーブルを作成してからルックアップを行うのに1秒もかかりません。

次に、他のより微妙な利点の一部を示します。PowerShell 3.0でのカスタムオブジェクトのデフォルト表示

3
Adam Driscoll

HashTableの代わりに[PSCustomObject]が使用される1つのシナリオは、それらのコレクションが必要な場合です。次に、それらの処理方法の違いを示します。

$Hash = 1..10 | %{ @{Name="Object $_" ; Index=$_ ; Squared = $_*$_} }
$Custom = 1..10 | %{[PSCustomObject] @{Name="Object $_" ; Index=$_ ; Squared = $_*$_} }

$Hash   | Format-Table -AutoSize
$Custom | Format-Table -AutoSize

$Hash   | Export-Csv .\Hash.csv -NoTypeInformation
$Custom | Export-Csv .\CustomObject.csv -NoTypeInformation

Format-Tableは、$Hashに対して次の結果になります。

Name    Value
----    -----
Name    Object 1
Squared 1
Index   1
Name    Object 2
Squared 4
Index   2
Name    Object 3
Squared 9
...

$CustomObjectについては次のとおりです。

Name      Index Squared
----      ----- -------
Object 1      1       1
Object 2      2       4
Object 3      3       9
Object 4      4      16
Object 5      5      25
...

Export-Csvでも同じことが起こります。したがって、単なるHashTableの代わりに[PSCustomObject]を使用する理由です。

29
tkokasih

フォルダーを作成するとします。 PSObjectを使用している場合、それを見て間違っていることがわかります。

PS > [PSObject] @{Path='foo'; Type='directory'}

Name                           Value
----                           -----
Path                           foo
Type                           directory

ただし、PSCustomObjectは正しいように見えます

PS > [PSCustomObject] @{Path='foo'; Type='directory'}

Path                                    Type
----                                    ----
foo                                     directory

オブジェクトをパイプできます

[PSCustomObject] @{Path='foo'; Type='directory'} | New-Item
17
Steven Penny

PSObjectの利点の1つは、それを使用してカスタムメソッドを作成できることです。

例えば、

$o = New-Object PSObject -Property @{
   "value"=9
}
Add-Member -MemberType ScriptMethod -Name "Sqrt" -Value {
    echo "the square root of $($this.value) is $([Math]::Round([Math]::Sqrt($this.value),2))"
} -inputObject $o

$o.Sqrt()

これを使用して、PSObjectプロパティの並べ替え順序を制御できます(PSObject並べ替えを参照)

12
Loïc MICHEL

PSObjectドキュメントから

オブジェクトをラップして、使用可能なメンバーの代替ビューとそれらを拡張する方法を提供します。メンバーは、メソッド、プロパティ、パラメータ化されたプロパティなどです。

つまり、PSObjectは、作成後にメソッドとプロパティを追加できるオブジェクトです。

「ハッシュテーブルについて」ドキュメントから

ハッシュテーブルは、辞書または連想配列とも呼ばれ、1つ以上のキー/値のペアを格納するコンパクトなデータ構造です。

...

ハッシュテーブルは、データの検索と取得に非常に効率的であるため、頻繁に使用されます。

PowerShellではPSObjectにプロパティを追加できるため、HashtableのようにPSObjectsを使用できますが、HashtableKeysプロパティなど、Values固有の機能へのアクセスを失うため、これを行うべきではありません。また、パフォーマンスコストと追加のメモリ使用量がある場合があります。

PowerShellドキュメントには、PSCustomObjectに関する以下の情報があります

パラメーターのないPSObjectのコンストラクターが使用される場合、プレースホルダーBaseObjectとして機能します。

これは私には不明瞭でしたが、 PowerShellフォーラムへの投稿 from PowerShellの多数の本の共著者 はより明確なようです:

[PSCustomObject]はタイプアクセラレータです。 PSObjectを構築しますが、ハッシュテーブルキーがプロパティになるように構築します。 PSCustomObjectは、それ自体はオブジェクトタイプではありません。プロセスのショートカットです。 ... PSCustomObjectは、コンストラクターパラメーターなしでPSObjectが呼び出されたときに使用されるプレースホルダーです。

コードに関して、@{a=1;b=2;c=3}Hashtableです。 [PSObject]@{a=1;b=2;c=3}は、HashtablePSObjectに変換したり、エラーを生成したりしません。オブジェクトはHashtableのままです。ただし、[PSCustomObject]@{a=1;b=2;c=3}は、HashtablePSObjectに変換します。これが起こる理由を説明したドキュメントを見つけることができませんでした。

プロパティ名としてキーを使用するためにHashtableをオブジェクトに変換する場合、次のコード行のいずれかを使用できます。

[PSCustomObject]@{a=1;b=2;c=3}

# OR

New-Object PSObject -Property @{a=1;b=2;c=3}

# NOTE: Both have the type PSCustomObject

多数のHashtablesを、キーがプロパティ名であるオブジェクトに変換する場合は、次のコードを使用できます。

@{name='a';num=1},@{name='b';num=2} |
 % { [PSCustomObject]$_ }

# OR

@{name='a';num=1},@{name='b';num=2} |
 % { New-Object PSObject -Property $_ }

<#
Outputs:

name num
---- ---
a      1
b      2
#>

NotePropertyに関するドキュメントを見つけることは困難でした。 Add-Memberドキュメント では、NoteProperty以外のオブジェクトプロパティを追加するのに意味のある-MemberTypeはありません。 Windows PowerShell Cookbook(第3版)では、Noteproperty Membertypeを次のように定義しました。

指定した初期値で定義されたプロパティ

  • リー、H。(2013)。 Windows PowerShell Cookbook。 O'Reilly Media、Inc. p。 895。
10
Dave F