将两个Bash数组通过笛卡尔积合并为键值对

51

我有两个数组 AB,如何将它们合并成一个新的数组C,该数组是它们的笛卡尔积?例如,给定:

A=( 0 1 )
B=( 1 2 )

期望的输出:

C=( 0:1 0:2 1:1 1:2 )
5个回答

157

如果您不关心重复项或保持索引,那么您可以使用以下代码将两个数组合并为一个:

NEW=("${OLD1[@]}" "${OLD2[@]}")

完整示例:

Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Shell=('bash' 'csh' 'jsh' 'rsh' 'ksh' 'rc' 'tcsh');
UnixShell=("${Unix[@]}" "${Shell[@]}")
echo ${UnixShell[@]}
echo ${#UnixShell[@]}

来源: http://www.thegeekstuff.com/2010/06/bash-array-tutorial/


12
这会连接两个数组,但这不是原帖作者想要的。 - Dennis Williamson
56
没问题,我理解了。以下是翻译内容:@DennisWilliamson,没错,但是谷歌会让成千上万的人来这里寻找答案。我很高兴这里有答案。 - Bruno Bronosky
2
虽然这是一种有用的技术,但也应该注意到源数组的索引会丢失。当创建目标数组时,会生成新的索引。 - Dennis Williamson
2
@Dave F,缺少“-n”不是数组连接的问题。它能够正常工作。这个选项缺失是因为“echo”将其解释为不输出换行符的选项。 - B. Ehlers
我不同意这种观点,即我们应该降低搜索引擎答案的质量,因为搜索引擎(尚未)足够明智,以允许毫无意义地点击而不阅读标题。这会导致垃圾进,垃圾出的未来。 - undefined
显示剩余3条评论

20

由于Bash支持稀疏数组,因此最好遍历数组而不是使用基于大小的索引。

a=(0 1); b=(2 3)
i=0
for z in ${a[@]}
do
    for y in ${b[@]}
    do
        c[i++]="$z:$y"
    done
done
declare -p c   # dump the array

输出:

declare -a c='([0]="0:2" [1]="0:3" [2]="1:2" [3]="1:3")'

4

这是一种方法

a=(0 1)
b=(1 2)
for((i=0;i<${#a[@]};i++));
do
    for ((j=0;j<${#b[@]};j++))
    do
        c+=(${a[i]}:${b[j]});
    done
done

for i in ${c[@]}
do
    echo $i
done

1
第二个 for 循环应该在数组引用周围使用双引号。这将保留数组值中的空格。尝试使用 a=("foo bar" "baz quux") 进行测试。同样,c+= 赋值需要引用新值。 - tripleee

0

以下是我在Bash中合并两个数组的方法:

示例数组:

AR=(1 2 3) BR=(4 5 6)

一行代码实现:

CR=($(echo ${AR[*]}) $(echo ${BR[*]}))


2
不需要使用$(),因为它不能保留值中的空格(如果存在的话)。a=("some words" some single words)b=(one two three "words with spaces")n=("${a[@]}" "${b[@]}")您也可以使用+=将一个数组附加到另一个数组末尾a+=("${b[@]}") - Matthew Hannigan
只有在每个元素都是以空格分隔的情况下才有效。如果您使用readarray根据行输入元素,则此方法将无法正常工作。 - Dave

-2

在Bash中合并两个数组的一行语句:

combine=( `echo ${array1[@]}` `echo ${array2[@]}` )

这将重新拆分元素。你可能想说的是 combine=("${array1[@]}" "${array2[@]}")。这也是 Ian Dunn 所说的。 - Toby Speight
引用错误会因为无用的echo使用而加剧。 - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接