Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign an associative array to another variable in zsh?

In zsh, is there a way to assign an associative array to another variable? I would like to to something like this:

typeset -A orig
orig=(key1 val1 key2 val2)
typeset -A other
other=$orig
print '$orig:  '$orig
print '$other: '$other
print '$orig[key1]: '$orig[key1]
print '$other[key1]: '$other[key1]

This will print:

$orig:  val1 val2
$other: val1 val2
$orig[key1]: val1
$other[key1]: 

I want to be able to use $other[key1] and get val1.

I know I can iterate over the keys and copy it item by item, but I really want to avoid this. Also, eval is evil :)

I have tried other=($orig) and other variations, but this will get my values from orig and create as associative array like this

other=(val1 val2)

So other[key1] returns nothing and other[val1] returns val2, which is not what I want.

If I understand correctly, what is going on in every attempt of mine is that $other is getting an array of the values of $orig, without the keys. How can I make it receive both keys and values and have the correct association between them?

I'm not worried about null values, if that would even be a problem, because I am sure $orig will be well behaved.

Thanks!

like image 256
Vitor Eiji Avatar asked Oct 09 '13 23:10

Vitor Eiji


People also ask

Does zsh support associative arrays?

One of the advantages of zsh over bash 3 is the support of “associative arrays,” a data structure known as hash tables or dictionaries in other languages.

Which function will create a new associative array by taking keys from one array and values from another?

Here array() function is used to create associative array.

Do Bash arrays start at 0 or 1?

The most important one: zsh arrays start at index position 1. bash arrays start at index position 0.


2 Answers

You have to delve into the wonderful world of parameter expansion flags :) The k and v flags can be used together to force an associative array to expand to both its keys and values.

$ typeset -A orig
$ orig=(key1 val1 key2 val2)
$ print ${(kv)orig}
key1 val1 key2 val2

Then you can use the set command to populate your copy with the alternating key/values produced by that expansion.

$ typeset -A other
$ set -A other ${(kv)orig}
$ print $other[key1]
val1

These and other flags are documented in man zshexpn under "Parameter Expansion Flags", which is one of my favorite zsh features.

like image 63
chepner Avatar answered Oct 06 '22 01:10

chepner


zsh: bad set of key/value pairs for associative array

Perfect world without escaping:

typeset -A old new
old=(k1 v1 k2 v2 k3 v3)
typeset old    # old=( k1 v1 k2 v2 k3 v3 )

...doesn't exist and your arrays usually include empty values:

old[k2]=
typeset old    # old=( k1 v1 k2 '' k3 v3 )

...therefore you need to use " (quoting), @ (escaping) and f (field separation):

typeset new    # new=( )
new=("${(@fkv)old}")
typeset new    # new=( k1 v1 k2 '' k3 v3 )

See man zshexpn for more on parameter expansion flags.

like image 41
cprn Avatar answered Oct 06 '22 01:10

cprn