none
Arrayのpropertyを作成し、要素を代入する RRS feed

  • 質問

  • こんにちは。

    Arrayを作成し、それにpropertyを追加したいのですが、うまくいきません。

    $final = New-Object System.Collections.ArrayList
    Add-Member  -InputObject $final -MemberType NoteProperty -Name Pair -Value $qqq.Pair -Force
    Add-Member  -InputObject $final -MemberType NoteProperty -Name eaname -Value $number.eaname -Force
    Add-Member  -InputObject $final -MemberType NoteProperty -Name number -Value $number.number -Force

    これを実行しても$finalにPair, eaname, numberのpropertyは作成されません。


    for ( $tt=0; $tt -lt $qqq.Length; $tt++)
     {
    $final += $qqq[$tt].Pair + $number[$tt].Eaname + $number[$tt].number
    }

    この結果は 
    $qqq.Pair $number,Eaname $number.number の 3つがくっついた配列ができ、
    $finalDevil.numberのようには参照できません。

     for ( $tt=0; $tt -lt $qqq.Length; $tt++)
     {
    $final.Add($qqq[$tt].Pair)
    $final.Add($number[$tt].Eaname)
    $final.Add($number[$tt].number)
    }

    これも同じ結果です。

     for ( $tt=0; $tt -lt $qqq.Length; $tt++)
     {
    $final.$($qqq[$tt].Pair) = $qqq[$tt].Pair
    $final.$($number[$tt].eaname) = $number[$tt].eaname
    $final.$($number[$tt].number) = $number[$tt].number
    }

    これはエラーになります。

    $finalDevil.numberのように参照できる配列、propertyをつくるにはどうしたらよいでしょうか?

    ちなみに、

    $qqqは

    Pair
    ------
    ABCDEF
    GHIJKL
    MNOPQR

    $numberは
    eaname                number
    ------------               ------------
    ahfgsytf                 1
    etroplkd                 6
    wrtjdmk                 z

    などのようになっています。
    $qqq[3].Pair  $number[7].number などと参照できます。




    2008年3月9日 1:19

回答

  • Associative Array(連想配列)は.NETの型名でいうとHashTableだと思うんですが、どちらもCollectionであると言う事を除いては、Arrayとは完全に別物だと考えたほうがわかりやすいかな、と思います。

    上に書いた例では、Arrayの要素にHashTableを利用していますが、これは
    $final[0]["eaname"]
     ↓
    $final[0].eaname
    と書ける事を利用しています。
    # 個人的には、この書き方はPropertyと混乱するのであまり嬉しくないかな、と思います。javascriptっぽい。

    Arrayの要素にArrayを使う(配列の配列、ジャグ配列)ことも出来るので、その場合、
    $final += ($qqq[$tt].Pair, $number[$tt].Eaname, $number[$tt].number)
    こう書いておけば、
    $final[0][0]でPair, $final[0][1]でEanameを参照できるとおもいます。

    pjo22さんの
    $final += $qqq[$tt].Pair + $number[$tt].Eaname + $number[$tt].number
    だと、まず右辺が全て結合され、それが配列に付け加えられてしまいます

    CollectionであるHashTableもArrayもそれ自体がオブジェクトなのでPropertyやMethodなどのMemberを持ちます。Collectionの要素もそれぞれMemberを持つので、そこを切り分けて考えるといいのではないかと思います。

    $final | Get-Member
    などとすると配列の要素のMemberが表示されてしまい混乱するので、
    $final.GetType()  ← Collection自体の型を取得
    とか、
    $final | ForEach-Object { $_.GetType() } ← Collectionの要素それぞれの型を取得
    とすると、Collectionと中身の違いがわかりやすいんじゃないかと思います。

    本はPowerShellインアクション(日本語版)を読んでいて、いい本だとは思うのですが、連想配列について特別わかりやすい説明がされているわけでも無いので、そういう意味ではお勧めではないです……。

    ArrayもHashTableも.NET Frameworkのクラスであり、また他の言語でも使用される概念なので、PowerShellでの説明にこだわらず、.NETとか一般の解説を読んで整理。その後PowerShell独特の表記(, 演算子とか、@()とか、@{}とか)を整理するといいんじゃないかなと思います。
    2008年3月9日 3:13

すべての返信

  • $final = New-Object System.Collections.ArrayList
    Add-Member  -InputObject $final -MemberType NoteProperty -Name Pair -Value $qqq.Pair -Force
    ↑このやり方だと、Pair Memberが追加されるのは$finalに対してであり、$finalの各要素にではありません。また、この時点では$finalには要素がないので、メンバーは追加できないのではないかとおもいます。

    各要素にPropertyを追加したいなら、forループの中でそのようなオブジェクトを作成してから、$finalにAddする必要があります。


    $final[0].numberのように参照したいだけならば、HashTableを要素に持つ配列を使用するのが簡単だと思います。
    $final = @()
    for ( $tt=0; $tt -lt $qqq.Length; $tt++) {
      $final += @{Pair = $qqq[$tt].Pair; eaname = $number[$tt].Eaname; number = $number[$tt].number }
    }
    2008年3月9日 2:00
  • 嗣永モモコーラさま

    ありがとうございます。
    うまく動作しました。

    小生の頭の中でAssociative Arrayと 通常arrayのpropertyとごちゃごちゃになっています。Windows Powershell Cookbookを読んでいますがどうもよくわかりません。
    PowerShell関連のサイトやブログもたくさん読んでいますが、どうも今ひとつ理解できていません。
    どこかにわかりやすい英語、日本語のサイトはないでしょうか?
    2008年3月9日 2:18
  • Associative Array(連想配列)は.NETの型名でいうとHashTableだと思うんですが、どちらもCollectionであると言う事を除いては、Arrayとは完全に別物だと考えたほうがわかりやすいかな、と思います。

    上に書いた例では、Arrayの要素にHashTableを利用していますが、これは
    $final[0]["eaname"]
     ↓
    $final[0].eaname
    と書ける事を利用しています。
    # 個人的には、この書き方はPropertyと混乱するのであまり嬉しくないかな、と思います。javascriptっぽい。

    Arrayの要素にArrayを使う(配列の配列、ジャグ配列)ことも出来るので、その場合、
    $final += ($qqq[$tt].Pair, $number[$tt].Eaname, $number[$tt].number)
    こう書いておけば、
    $final[0][0]でPair, $final[0][1]でEanameを参照できるとおもいます。

    pjo22さんの
    $final += $qqq[$tt].Pair + $number[$tt].Eaname + $number[$tt].number
    だと、まず右辺が全て結合され、それが配列に付け加えられてしまいます

    CollectionであるHashTableもArrayもそれ自体がオブジェクトなのでPropertyやMethodなどのMemberを持ちます。Collectionの要素もそれぞれMemberを持つので、そこを切り分けて考えるといいのではないかと思います。

    $final | Get-Member
    などとすると配列の要素のMemberが表示されてしまい混乱するので、
    $final.GetType()  ← Collection自体の型を取得
    とか、
    $final | ForEach-Object { $_.GetType() } ← Collectionの要素それぞれの型を取得
    とすると、Collectionと中身の違いがわかりやすいんじゃないかと思います。

    本はPowerShellインアクション(日本語版)を読んでいて、いい本だとは思うのですが、連想配列について特別わかりやすい説明がされているわけでも無いので、そういう意味ではお勧めではないです……。

    ArrayもHashTableも.NET Frameworkのクラスであり、また他の言語でも使用される概念なので、PowerShellでの説明にこだわらず、.NETとか一般の解説を読んで整理。その後PowerShell独特の表記(, 演算子とか、@()とか、@{}とか)を整理するといいんじゃないかなと思います。
    2008年3月9日 3:13
  • 嗣永モモコーラさま

    たいへんわかりやすい解説をありがとうございます。

    PowerShellは、.NET, WMI, RegExなどさまざまな要素が扱える高機能が謳い文句なのでしょうが、
    それぞれは1冊のぶ厚い本が必要な情報量なので、 codingにまで到達するのに難儀します。

    特に.PowerShellでNETをどう使うかを詳しく書いた書籍またはWebサイトがもっとあればよいなと感じています。
    2008年3月9日 6:29