如何从数组数组中检索项目?

如何从数组数组中检索项目?

StackExchange 专业人士您好!

我正在开发一个适用于 macOS 的 zsh 项目。我使用排版创建了三个关联数组来保存值,以及第四个数组来引用各个数组。是否可以迭代 arrCollection 以从每个成员数组中检索键/值对?请注意,下面数组中的键与我的生产脚本不同 - 它们只是键索引,而不是您可能在关联数组中找到的更具描述性的键。

我想我可以像这样使用参数扩展:

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

但我不太正确。有人可以帮忙吗?预期输出将是由换行符分隔的所有三个数组中的所有项目的列表。

下面是完整的脚本示例。用法: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 开始的连续十进制数时,不确定为什么您使用关联数组而不是普通数组,但如果我正确理解您想要什么,您可以这样做:

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(数字)排序参数扩展标志。与这些元素相比,元素使用区域设置排序规则进行比较,但由十进制数字序列组成的部分除外。十进制数字序列被解释为十进制整数并进行数值比较。

sort这与GNU 实现对-V/选项的作用类似--version-sort

例如,因此foo2-3会出现在 beforefoo10-3和 before foo2-10,但不能用于除正十进制整数以外的数字(-2也会出现在 before-102.3before 2.10)。

sort要使用其他任意标准进行排序,虽然 zsh 中存在以内置方式执行此操作的复杂方法,但如果您可以保证元素不包含 NL 或 NUL 字符并且不为空,则可能更容易采用。

以 GNU 为例sort

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

以数字方式循环非空键,但这次支持各种数字表示形式(包括 0x20、1e-1、无穷大、-20、0x3.fp5...)。

上面使用 NUL 分隔记录将列表提供给列表sort并分割其输出,因此假设键不包含 NUL 字符。要改用 NL/LF 字符,请删除-N,-z并更改(0)(f)


1 和 NUL 字符必须单独处理,因为标准比较 API 会阻塞它们。

相关内容