配列の配列から項目を取得する方法は?

配列の配列から項目を取得する方法は?

こんにちは、StackExchangeの専門家の皆さん!

私はmacOS用のzshプロジェクトに取り組んでいます。組版を使用して、値を保持する3つの連想配列と個々の配列を参照する4番目の配列を作成しました。各メンバー配列でキーと値のペアを取得するためにarrCollectionを繰り返すことはできますか?以下の配列のキーは私の本番スクリプトとは異なります。これはキーインデックスにすぎず、連想配列で見つけることができるより説明的なキーではありません。

次のようにパラメータ拡張を使用できるようです。

for k in $(sort <<< "${(kvF)arrCollection}"); do
   echo "$arrCollection["${(kvF)k}"]"
done

しかし、私は完全に正しくありません。誰でも助けることができますか?予想される出力は、改行文字で区切られた3つの配列すべてのすべての項目のリストです。

以下は完全なスクリプトの例です。使用法: arrTest.sh showAll

#!/bin/zsh

key=$1

typeset -A arrOne arrTwo arrThree
typeset -A arrCollection

#Plan is to use an array of arrays so that a for loop can be used later to loop
#through each key/value pair looking for a value that matches some pattern in an if statement
#(if statement not included here). In the showAll case, how can I use parameter expansion to print all
#of the values in each array? The if statement will further constrict what is actually echoed based on its
#value.

arrOne[1]="First"
arrOne[2]="Second"
arrOne[3]="Third"
arrOne[4]="Fourth"

arrTwo[1]="Purple"
arrTwo[2]="Orange"
arrTwo[3]="Red"
arrTwo[4]="Green"
arrTwo[5]="Blue"

arrThree[1]="First"
arrThree[2]="Red"
arrThree[3]="Planet"
arrThree[4]="Sun"
arrThree[5]="Moon"
arrThree[6]="Star"

#Array of arrays
arrCollection[1]=arrOne
arrCollection[2]=arrTwo
arrCollection[3]=arrThree

#Expect a parameter
if [ -z "$key" ]
then
    echo "Please enter a parameter"
else
    case "$key" in
    showAll)
        for k in $(sort <<< "${(kvF)arrCollection}"); do
            #This is the part I am having trouble with
            echo "$arrCollection["${(kvF)k}"]"
        done
        exit 1
    ;;
    *)
        echo "Something goes here"
        exit 1
    ;;
    esac
fi

答え1

キーが1から始まる連続した10進数の場合、通常の配列の代わりに連想配列を使用する理由はわかりませんが、必要なものを正しく理解すると、次のことができます。

for key in "${(nok@)arrCollection}"; do
  print -r - "Assoc $key: $arrCollection[$key]"
  printf ' "%s" => "%s"\n' "${(@kvP)arrCollection[$key]}"
done

サンプルは次の内容を提供する必要があります。

Assoc 1: arrOne
 "3" => "Third"
 "4" => "Fourth"
 "1" => "First"
 "2" => "Second"
Assoc 2: arrTwo
 "3" => "Red"
 "4" => "Green"
 "5" => "Blue"
 "1" => "Purple"
 "2" => "Orange"
Assoc 3: arrThree
 "3" => "Planet"
 "4" => "Sun"
 "5" => "Moon"
 "6" => "Star"
 "1" => "First"
 "2" => "Red"

または、関連する各メンバーをキーに基づいて数値順に並べ替えることもできます。

for key in "${(nok@)arrCollection}"; do
  print -r - "Assoc $key: $arrCollection[$key]"
  for assoc_key in "${(@knoP)arrCollection[$key]}"; do
    printf ' "%s" => "%s"\n' "$assoc_key" "${${(P)arrCollection[$key]}[$assoc_key]}"
  done
done

これにより、以下が提供されます。

Assoc 1: arrOne
 "1" => "First"
 "2" => "Second"
 "3" => "Third"
 "4" => "Fourth"
Assoc 2: arrTwo
 "1" => "Purple"
 "2" => "Orange"
 "3" => "Red"
 "4" => "Green"
 "5" => "Blue"
Assoc 3: arrThree
 "1" => "First"
 "2" => "Red"
 "3" => "Planet"
 "4" => "Sun"
 "5" => "Moon"
 "6" => "Star"

o上記のキーは、n(シーケンス)と(番号)を使用してソートされます。パラメータ拡張フラグ。これらの要素と比較すると、要素は10進数のシーケンスで構成される部分を除いて、ロケールの組み合わせを使用して比較されます。 10 進数シーケンスは 10 進整数として解釈され、数値として比較されます。

sortこれは、GNU実装で-V/オプションを使用して実行する操作と似ています--version-sort

たとえば、foo2-3beforefoo10-3とbeforeに表示されますが、正の10進整数(beforeおよびbeforeにも表示されます)foo2-10以外の数字には使用できません。-2-102.32.10

sort他の任意の基準を使用してソートするには、zshに組み込まれているこの操作を実行するための複雑な方法がありますが、要素にNLまたはNUL文字が含まれていないか空でないことを保証できる場合は簡単です。

GNUを例に挙げましょうsort

for key in ${(0)"$(print -rNC1 -- ${(k)arrCollection} | sort -zg)"}

NULL以外のキーを数字で繰り返しますが、今回はさまざまな数値表現(0x20、1e-1、無限大、-20、0x3.fp5...を含む)をサポートします。

上記は、NULで区切られたレコードを使用してリストを提供し、出力を分割するsortため、キーにNUL文字が含まれていないと想定されます。代わりにNL / LF文字を使用するには、を削除して-N-z変更します。(0)(f)


1 文字と NUL 文字は標準比較 API でブロックされるため、個別に処理する必要があります。

関連情報