7

Powershellで興味深い問題が発生しましたが、解決策を見つけることができませんでした。私がグーグルで検索すると(そしてこの投稿のようなものを見つけると)、私がやろうとしていることほど複雑なことは何も起こらないので、ここに質問を投稿しようと思いました。

問題は、外側の配列の長さが1の多次元配列に関係しています。Powershellは、に@( @('A') )なるように配列を平坦化することに非常に固執しているよう@( 'A' )です。これが最初のスニペットです(プロンプトは>、ところで):

> $a =  @( @( 'Test' ) )
> $a.gettype().isarray
True
> $a[0].gettype().isarray
False

したがって、$a[0].gettype().isarray値を次のようにインデックス付けできるように、trueにします$a[0][0](実際のシナリオでは、ループ内で動的配列を処理し、値をとして取得したいのです$a[$i][$j]が、内部アイテムが配列としてではなく文字列として認識されます(私の場合)、のように、文字列の文字へのインデックス作成を開始します$a[0][0] -eq 'T'

長いコード例がいくつかあるので、最後に投稿しました。また、参考までに、これはPSv2とPSCXがインストールされたWindows7Ultimateにあります。

コード例1を考えてみましょう。+=演算子を使用して手動で単純な配列を作成します。中間配列$wはフラット化されているため、最終配列に正しく追加されません。私は同様の問題の解決策をオンラインで見つけました。基本的には、内側の配列の前にコンマを配置して、外側の配列をフラットにしないようにします。これは機能しますが、ループ内に配列を構築できる解決策を探しています(配列のギザギザの配列、CSSファイルの処理)、したがって、先頭のコンマを単一の要素配列(中間配列として実装$y)に追加すると、他の配列(など)にも同じことをしたいのです$zが、悪影響がありますどのよう$zに最終的な配列に追加されますか。

ここでコード例2を考えてみましょう:これは私が抱えている実際の問題に近いものです。1つの要素を持つ多次元配列が関数から返されると、それはフラット化されます。関数を離れる前に正しいです。繰り返しになりますが、これらは例です。関数が戻ってくるのか、戻ってくるのかを知らなくても、実際にファイルを処理しようとしています@( @( 'color', 'black') )@( @( 'color', 'black'), @( 'background-color', 'white') )

誰かがこれに遭遇しましたか、そして誰かがこれを解決しましたか?フレームワークオブジェクトをインスタンス化できることはわかっています。object[]やlist<>などを作成すれば、すべて問題ないと思いますが、これについては少しの間取り組んできました。確かに、これを行うには正しい方法が必要なようです(真のフレームワークオブジェクトをインスタンス化する必要はありません)。

コード例1

function Display($x, [int]$indent, [string]$title)
{
  if($title -ne '') { write-host "$title`: " -foregroundcolor cyan -nonewline }
  if(!$x.GetType().IsArray)
  { write-host "'$x'" -foregroundcolor cyan }
  else
  {
    write-host ''
    $s = new-object string(' ', $indent)
    for($i = 0; $i -lt $x.length; $i++)
    {
      write-host "$s[$i]: " -nonewline -foregroundcolor cyan
      Display $x[$i] $($indent+1)
    }
  }
  if($title -ne '') { write-host '' }
}


### Start Program
$final = @( @( 'a', 'b' ), @('c'))
Display $final 0 'Initial Value'

### How do we do this part ??? ###########
                                        ##
$w = @( @('d', 'e') )                   ##
$x = @( @('f', 'g'), @('h') )           ##
# But now $w is flat, $w.length = 2     ##
                                        ##
                                        ##
# Even if we put a leading comma (,)    ##
# in front of the array, $y will work   ##
# but $w will not. This can be a        ##
# problem inside a loop where you don't ##
# know the length of the array, and you ##
# need to put a comma in front of       ##
# single- and multidimensional arrays.  ##
$y = @( ,@('D', 'E') )                  ##
$z = @( ,@('F', 'G'), @('H') )          ##
                                        ##
                                        ##
##########################################

$final += $w
$final += $x
$final += $y
$final += $z
Display $final 0 'Final Value'


### Desired final value: @( @('a', 'b'), @('c'), @('d', 'e'), @('f', 'g'), @('h'), @('D', 'E'), @('F', 'G'), @('H') )
### As in the below:
# 
# Initial Value:
# [0]:
#  [0]: 'a'
#  [1]: 'b'
# [1]:
#  [0]: 'c'
# 
# Final Value:
# [0]:
#  [0]: 'a'
#  [1]: 'b'
# [1]:
#  [0]: 'c'
# [2]:
#  [0]: 'd'
#  [1]: 'e'
# [3]:
#  [0]: 'f'
#  [1]: 'g'
# [4]:
#  [0]: 'h'
# [5]:
#  [0]: 'D'
#  [1]: 'E'
# [6]:
#  [0]: 'F'
#  [1]: 'G'
# [7]:
#  [0]: 'H'

コード例2

function Display($x, [int]$indent, [string]$title)
{
  if($title -ne '') { write-host "$title`: " -foregroundcolor cyan -nonewline }
  if(!$x.GetType().IsArray)
  { write-host "'$x'" -foregroundcolor cyan }
  else
  {
    write-host ''
    $s = new-object string(' ', $indent)
    for($i = 0; $i -lt $x.length; $i++)
    {
      write-host "$s[$i]: " -nonewline -foregroundcolor cyan
      Display $x[$i] $($indent+1)
    }
  }
  if($title -ne '') { write-host '' }
}



function funA()
{
  $ret = @()
  $temp = @(0)
  $temp[0] = @('p', 'q')
  $ret += $temp
  Display $ret 0 'Inside Function A'
  return $ret # What about return ,$ret ? What about if $ret = @( @('p', 'q'), @('r', 's') ) -- would return ,$ret still work?
}

function funB()
{
  $ret = @( ,@('r', 's') )
  Display $ret 0 'Inside Function B'
  return $ret
}


### Start Program

$z = funA
Display $z 0 'Return from Function A'
$z = funB
Display $z 0 'Return from Function B'


### Desired final value: @( @('p', 'q') )  and same for r,s
### As in the below:
# 
# Inside Function A:
# [0]:
#  [0]: 'p'
#  [1]: 'q'
# 
# Return from Function A:
# [0]:
#  [0]: 'p'
#  [1]: 'q'

ありがとう、マット

4

2 に答える 2

7

同じ問題から始まる別の質問があります:Powershellの落とし穴。これは設計によるもののようです。

,$retの代わりに戻って来ればうまくいくと思います$ret

さらに2つのメモ:

  • アイテムが配列であるかどうかをテストできます$item -is [array](PowerShellに似ているという理由だけで;)
  • @()配列ではないアイテムにのみ影響します。をチェーン@(@(@(1)))すると、1つのintアイテムを含む配列が得られます(@(@(@(1)))[0].gettype()Int32を返します)。
    だから、@( ,@('r', 's') )と同じ,@('r', 's')です。
于 2010-03-17T21:20:30.040 に答える
0

この例を使用して、stejが言ったことを試しましたが、うまくいきました。

function funC([int]$numOfPairs)
{
  $ret = @()
  if($numOfPairs -eq 1)
  { $ret = ,@('r','s') }
  elseif($numOfPairs -eq 2)
  { $ret = @('r','s'),@('t','u') }
  else
  { $ret = @('r','s'),@('t','u'),@('v','w') }

  Display $ret 0 "Inside Function C ($numOfPairs)"
  return ,$ret
}


### Start Program

$z = funC 1
Display $z 0 'Return from Function C(1)'
$z = funC 2
Display $z 0 'Return from Function C(2)'
$z = funC 3
Display $z 0 'Return from Function C(3)'
于 2010-03-19T13:09:44.830 に答える