* How to iterate over an array of associative arrays
@ 2013-07-14 12:35 Thorsten Kampe
2013-07-14 13:10 ` Mikael Magnusson
0 siblings, 1 reply; 10+ messages in thread
From: Thorsten Kampe @ 2013-07-14 12:35 UTC (permalink / raw)
To: zsh-users
Hi,
I'd like to iterate over elements of an array. The elements are
associative arrays. This is my code:
"""
#! /usr/bin/env zsh
emulate -R zsh
setopt nounset
declare -A elem AssocArr1 AssocArr2
AssocArr1=(key value1)
AssocArr2=(key value2)
array=($AssocArr1 $AssocArr2)
for elem in $array
do echo $elem[key]
done
"""
./test.zsh:14: elem[key]: parameter not set
Thorsten
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 12:35 How to iterate over an array of associative arrays Thorsten Kampe
@ 2013-07-14 13:10 ` Mikael Magnusson
2013-07-14 13:36 ` Thorsten Kampe
0 siblings, 1 reply; 10+ messages in thread
From: Mikael Magnusson @ 2013-07-14 13:10 UTC (permalink / raw)
To: Thorsten Kampe; +Cc: Zsh Users
On 14 July 2013 14:35, Thorsten Kampe <thorsten@thorstenkampe.de> wrote:
> Hi,
>
> I'd like to iterate over elements of an array. The elements are
> associative arrays. This is my code:
>
> """
> #! /usr/bin/env zsh
> emulate -R zsh
>
> setopt nounset
>
> declare -A elem AssocArr1 AssocArr2
>
> AssocArr1=(key value1)
> AssocArr2=(key value2)
>
> array=($AssocArr1 $AssocArr2)
Do you really want these $ here?
> for elem in $array
> do echo $elem[key]
> done
> """
>
> ./test.zsh:14: elem[key]: parameter not set
You need to use the (P) flag to access a parameter indirectly.
% foo=(one two)
% bar=foo
% echo $bar[2]
o
% echo ${${bar}[2]}
o
% echo ${${(P)bar}[2]}
two
--
Mikael Magnusson
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 13:10 ` Mikael Magnusson
@ 2013-07-14 13:36 ` Thorsten Kampe
2013-07-14 16:14 ` Valodim Skywalker
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Thorsten Kampe @ 2013-07-14 13:36 UTC (permalink / raw)
To: zsh-users
* Mikael Magnusson (Sun, 14 Jul 2013 15:10:22 +0200)
> On 14 July 2013 14:35, Thorsten Kampe <thorsten@thorstenkampe.de>
wrote:
> > Hi,
> >
> > I'd like to iterate over elements of an array. The elements are
> > associative arrays. This is my code:
> >
> > """
> > #! /usr/bin/env zsh
> > emulate -R zsh
> >
> > setopt nounset
> >
> > declare -A elem AssocArr1 AssocArr2
> >
> > AssocArr1=(key value1)
> > AssocArr2=(key value2)
> >
> > array=($AssocArr1 $AssocArr2)
>
> Do you really want these $ here?
Yes, I really wanted to pass the actual associative arrays, but if I can
pass the names that's fine with me, too.
> You need to use the (P) flag to access a parameter indirectly.
> % foo=(one two)
> % bar=foo
> % echo $bar[2]
> o
> % echo ${${bar}[2]}
> o
> % echo ${${(P)bar}[2]}
> two
Doesn't work for me:
"""
array=(AssocArr1 AssocArr2)
for elem in $array
do echo ${${(P)elem}[key]}
done
"""
[empty output]
Thorsten
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 13:36 ` Thorsten Kampe
@ 2013-07-14 16:14 ` Valodim Skywalker
2013-07-14 16:49 ` Thorsten Kampe
2013-07-14 17:21 ` Peter Stephenson
2013-07-14 18:05 ` Bart Schaefer
2 siblings, 1 reply; 10+ messages in thread
From: Valodim Skywalker @ 2013-07-14 16:14 UTC (permalink / raw)
To: zsh-users
[-- Attachment #1: Type: text/plain, Size: 354 bytes --]
I couldn't get that to work, either. The associative part seems to be
lost after (P) indirection, since elements can be addressed numerically.
Anyways, here's an alternative suggestion:
typeset -A a1 a2;
arr=( a2 a1 ); a1=(key val1); a2=(key val2);
for i in $arr; echo ${(e):-\$$i\[key]}
This uses (e), so beware of security implications.
- V
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 16:14 ` Valodim Skywalker
@ 2013-07-14 16:49 ` Thorsten Kampe
2013-07-14 17:25 ` Valodim Skywalker
0 siblings, 1 reply; 10+ messages in thread
From: Thorsten Kampe @ 2013-07-14 16:49 UTC (permalink / raw)
To: zsh-users
* Valodim Skywalker (Sun, 14 Jul 2013 18:14:37 +0200)
>
> I couldn't get that to work, either. The associative part seems to be
> lost after (P) indirection, since elements can be addressed numerically.
>
> Anyways, here's an alternative suggestion:
>
> typeset -A a1 a2;
> arr=( a2 a1 ); a1=(key val1); a2=(key val2);
> for i in $arr; echo ${(e):-\$$i\[key]}
>
> This uses (e), so beware of security implications.
...works. What for christ's sake does it do? (Of course, I could try to
figure it out on my own, but that might take a few days...)
Thorsten
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 13:36 ` Thorsten Kampe
2013-07-14 16:14 ` Valodim Skywalker
@ 2013-07-14 17:21 ` Peter Stephenson
2013-07-14 19:57 ` Thorsten Kampe
2013-07-14 18:05 ` Bart Schaefer
2 siblings, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 2013-07-14 17:21 UTC (permalink / raw)
To: zsh-users
On Sun, 14 Jul 2013 15:36:03 +0200
Thorsten Kampe <thorsten@thorstenkampe.de> wrote:
> Yes, I really wanted to pass the actual associative arrays, but if I can
> pass the names that's fine with me, too.
So maybe you're looking for:
typeset -A AssocArr1 AssocArr2
typeset -a array
typeset key value
AssocArr1=(key1 value1)
AssocArr2=(key2 value2)
# array is a normal array containing key/value pairs
array=(${(kv)AssocArr1} ${(kv)AssocArr2})
# scan array by pairs
for key value in $array
do echo $key $value
done
?
--
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 16:49 ` Thorsten Kampe
@ 2013-07-14 17:25 ` Valodim Skywalker
0 siblings, 0 replies; 10+ messages in thread
From: Valodim Skywalker @ 2013-07-14 17:25 UTC (permalink / raw)
To: zsh-users
[-- Attachment #1: Type: text/plain, Size: 275 bytes --]
The (e) flag is basically eval for parameter expansion. Using :-, an
inline string is created which looks like $a1[key], where the $ is the
escaped one, the a1 comes from $i, and \[key] is just added, escaping
the [ so it's not used as array subscript of $i.
Cheers,
- V
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 13:36 ` Thorsten Kampe
2013-07-14 16:14 ` Valodim Skywalker
2013-07-14 17:21 ` Peter Stephenson
@ 2013-07-14 18:05 ` Bart Schaefer
2 siblings, 0 replies; 10+ messages in thread
From: Bart Schaefer @ 2013-07-14 18:05 UTC (permalink / raw)
To: Thorsten Kampe, zsh-users
On Jul 14, 3:36pm, Thorsten Kampe wrote:
}
} > > AssocArr1=(key value1)
} > > AssocArr2=(key value2)
} > >
} > > array=($AssocArr1 $AssocArr2)
} >
} > Do you really want these $ here?
}
} Yes, I really wanted to pass the actual associative arrays, but if I can
} pass the names that's fine with me, too.
The shell language is text-oriented and can be though of as strictly
pass-by-value, so there's no way to create a nested data structure; the
values of the array cannot be direct references to other arrays.
} > You need to use the (P) flag to access a parameter indirectly.
Ksh namerefs, which are partly emulated by zsh's (P) flag, allow you to
simulate references but are not true object handles.
} Doesn't work for me:
}
} """
} array=(AssocArr1 AssocArr2)
}
} for elem in $array
} do echo ${${(P)elem}[key]}
} done
} """
Unfortunately even though ${(P)elem} can access by reference, it can only
"return" (expand that reference) by value, and the shell has only two kinds
of values: strings or plain arrays.
Fortunately, although associative array keys/values are not maintained in
any predictable order, they are guaranteed to be returned in a consistent
order (as long as no new elements are inserted between accesses) so this
can be done:
"""
declare -A AssocArr
AssocArr=(key1 value1 key2 value2 key3 value3)
ref=AssocArr
print position of key2 is ${${(kP)ref}[(i)key2]}
print value for key2 is ${${(P)ref}[${${(@kP)ref}[(i)key2]}]}
"""
The extra (@) in there is because $arr[key] puts key in double-quoted
context, so you have to force ${(P)ref} to remain an array for the
subscript operation.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 17:21 ` Peter Stephenson
@ 2013-07-14 19:57 ` Thorsten Kampe
2013-07-14 22:57 ` Bart Schaefer
0 siblings, 1 reply; 10+ messages in thread
From: Thorsten Kampe @ 2013-07-14 19:57 UTC (permalink / raw)
To: zsh-users
* Peter Stephenson (Sun, 14 Jul 2013 18:21:17 +0100)
> On Sun, 14 Jul 2013 15:36:03 +0200
> Thorsten Kampe <thorsten@thorstenkampe.de> wrote:
> > Yes, I really wanted to pass the actual associative arrays, but if I can
> > pass the names that's fine with me, too.
>
> So maybe you're looking for:
>
> typeset -A AssocArr1 AssocArr2
> typeset -a array
> typeset key value
>
> AssocArr1=(key1 value1)
> AssocArr2=(key2 value2)
>
> # array is a normal array containing key/value pairs
> array=(${(kv)AssocArr1} ${(kv)AssocArr2})
>
> # scan array by pairs
> for key value in $array
> do echo $key $value
> done
Looks good but as far as I can see it does not allow me to iterate over
assiociative arrays so I can get the value of a certain key from all
arrays.
Say I have...
AssocArr1=(key1 value11
key2 value12)
AssocArr2=(key1 value21
key2 value22)
So how do I iterate over...
array=(AssocArr1 AssocArr2)
...so that I get value12 (= AssocArr1[key2]) in the first iteration and
value22 (= AssocArr2[key2]) in the second?
Thorsten
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to iterate over an array of associative arrays
2013-07-14 19:57 ` Thorsten Kampe
@ 2013-07-14 22:57 ` Bart Schaefer
0 siblings, 0 replies; 10+ messages in thread
From: Bart Schaefer @ 2013-07-14 22:57 UTC (permalink / raw)
To: Thorsten Kampe, zsh-users
On Jul 14, 9:57pm, Thorsten Kampe wrote:
}
} Say I have...
}
} AssocArr1=(key1 value11
} key2 value12)
}
} AssocArr2=(key1 value21
} key2 value22)
}
} So how do I iterate over...
}
} array=(AssocArr1 AssocArr2)
Using the example in my earlier email ...
for ref in $array
do
print ${${(P)ref}[${${(@kP)ref}[(i)key2]}]}
done
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-07-14 22:57 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-14 12:35 How to iterate over an array of associative arrays Thorsten Kampe
2013-07-14 13:10 ` Mikael Magnusson
2013-07-14 13:36 ` Thorsten Kampe
2013-07-14 16:14 ` Valodim Skywalker
2013-07-14 16:49 ` Thorsten Kampe
2013-07-14 17:25 ` Valodim Skywalker
2013-07-14 17:21 ` Peter Stephenson
2013-07-14 19:57 ` Thorsten Kampe
2013-07-14 22:57 ` Bart Schaefer
2013-07-14 18:05 ` Bart Schaefer
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).