zsh-workers
 help / color / mirror / code / Atom feed
* Implement an "array index" subscript flag
@ 2018-06-08  1:37 Michael Milton
  2018-06-08  5:16 ` dana
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Milton @ 2018-06-08  1:37 UTC (permalink / raw)
  To: zsh-workers


[-- Attachment #1.1: Type: text/plain, Size: 1005 bytes --]

Hi all,


A useful feature for zsh would be the ability to convert an array into an array of keys/indexes for that array. For example, converting (a b c d) into (1 2 3 4)


Bash has a syntax for this, with the ${!array[@]} expansion, e.g.

vals=(a b c d)
keys=${!ids[@]}

Could we perhaps add another "Subscript Flag" to zsh, such that it evaluates the array into its indexes? For example, it might be ${(x)array[@]}, such that you could use it like this:
vals=(a b c d)
keys=${(x)ids[@]}

I suspect there is some desire for a feature like this, because there is a StackExchange question on the subject for zsh: https://unix.stackexchange.com/questions/334048/obtain-the-index-of-the-array, as well as a very high profile question for bash: https://stackoverflow.com/questions/6723426/looping-over-arrays-printing-both-index-and-value.

I'd be happy to contribute such a feature but I'm not sure what the contribution process actually is.


[1487806188587_VLSCI-MelbBioinfo-sign.png]

[-- Attachment #1.2: Type: text/html, Size: 3117 bytes --]

[-- Attachment #2: Outlook-1487806188.png --]
[-- Type: image/png, Size: 32868 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Implement an "array index" subscript flag
  2018-06-08  1:37 Implement an "array index" subscript flag Michael Milton
@ 2018-06-08  5:16 ` dana
  2018-06-08  5:46   ` Michael Milton
  2018-06-08  8:25   ` Peter Stephenson
  0 siblings, 2 replies; 6+ messages in thread
From: dana @ 2018-06-08  5:16 UTC (permalink / raw)
  To: zsh-workers; +Cc: Michael Milton

On 7 Jun 2018, at 20:37, Michael Milton <michael.milton@unimelb.edu.au> wrote:
>A useful feature for zsh would be the ability to convert an array into an array
>of keys/indexes for that array.... Bash has a syntax for this, with the
>${!array[@]} expansion

zsh actually has the (k) flag for this, but it only works on associations. zsh
also supports the ! syntax (which bash 3 borrowed from ksh93) when in ksh-
emulation mode, but since it's effectively an alias for (k) it *also* works only
on associations. To be clear, in both bash 4 and ksh93 it works as expected on
both.

I feel like the intuitive thing would be for (k) and (v) to work on arrays
equivalently to the way they work on associations. In other words...

  % arr=( foo bar baz )
  % print ${(k)arr}
  1 2 3
  % print ${(kv)arr}
  1 foo 2 bar 3 baz

Looking at the manual, it seems to me that the current effect of those two flags
on arrays is actually undefined (except when used in conjunction with a
subscript), so... would that not be a reasonable change to make, if someone were
inclined?

Looks like Oliver was considering exactly that, once upon a time:
http://www.zsh.org/mla/workers/2004/msg00226.html

In the mean time, though, like the Stack Exchange link says — since zsh doesn't
support sparse arrays, i think {1..$#arr} is almost exactly equivalent to (the
hypothetical) ${(k)arr}.

dana


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Implement an "array index" subscript flag
  2018-06-08  5:16 ` dana
@ 2018-06-08  5:46   ` Michael Milton
  2018-06-08  6:15     ` dana
  2018-06-08  8:25   ` Peter Stephenson
  1 sibling, 1 reply; 6+ messages in thread
From: Michael Milton @ 2018-06-08  5:46 UTC (permalink / raw)
  To: dana, zsh-workers

[-- Attachment #1: Type: text/plain, Size: 2253 bytes --]

I like this solution. If we change (k) to work with arrays, then it sounds like it would allow the bash ${!array[@]} syntax to work identically, which is another benefit.


Although incidentally, I don't have any success using (k) even with associative arrays. Perhaps I'm misunderstanding? This produces no output:

arr=([1]=a [2]=b)
keys=${arr[(k)@]}
echo $keys


My only other concern is that it sounds like (k) actually does pattern matching to look up the index of each value. Does this have performance implications? Would it not be simpler to just return the underlying array positions (depending on how arrays are implemented)?

________________________________
From: dana <dana@dana.is>
Sent: Friday, 8 June 2018 3:16 PM
To: zsh-workers@zsh.org
Cc: Michael Milton
Subject: Re: Implement an "array index" subscript flag

On 7 Jun 2018, at 20:37, Michael Milton <michael.milton@unimelb.edu.au> wrote:
>A useful feature for zsh would be the ability to convert an array into an array
>of keys/indexes for that array.... Bash has a syntax for this, with the
>${!array[@]} expansion

zsh actually has the (k) flag for this, but it only works on associations. zsh
also supports the ! syntax (which bash 3 borrowed from ksh93) when in ksh-
emulation mode, but since it's effectively an alias for (k) it *also* works only
on associations. To be clear, in both bash 4 and ksh93 it works as expected on
both.

I feel like the intuitive thing would be for (k) and (v) to work on arrays
equivalently to the way they work on associations. In other words...

  % arr=( foo bar baz )
  % print ${(k)arr}
  1 2 3
  % print ${(kv)arr}
  1 foo 2 bar 3 baz

Looking at the manual, it seems to me that the current effect of those two flags
on arrays is actually undefined (except when used in conjunction with a
subscript), so... would that not be a reasonable change to make, if someone were
inclined?

Looks like Oliver was considering exactly that, once upon a time:
http://www.zsh.org/mla/workers/2004/msg00226.html

In the mean time, though, like the Stack Exchange link says — since zsh doesn't
support sparse arrays, i think {1..$#arr} is almost exactly equivalent to (the
hypothetical) ${(k)arr}.

dana


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Implement an "array index" subscript flag
  2018-06-08  5:46   ` Michael Milton
@ 2018-06-08  6:15     ` dana
  2018-06-08  6:27       ` Michael Milton
  0 siblings, 1 reply; 6+ messages in thread
From: dana @ 2018-06-08  6:15 UTC (permalink / raw)
  To: zsh-workers; +Cc: Michael Milton

On 8 Jun 2018, at 00:46, Michael Milton <michael.milton@unimelb.edu.au> wrote:
>This produces no output:
>arr=([1]=a [2]=b)
>keys=${arr[(k)@]}
>echo $keys

You're talking about the (k) subscript flag; i meant the (k) expansion flag. See
the hypothetical example in my earlier reply for how the latter works (just use
an association instead of an array). The former isn't relevant here (array
indexes aren't useful as patterns anyway), but it works like this:

  % local -A assoc=( 'a*' val1 '*a' val2 )
  % print ${assoc[(k)abc]}
  val1
  % print ${assoc[(k)cba]}
  val2

If the (k) expansion flag were made to work on indexed arrays it would
definitely not need to do any pattern matching.

dana


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Implement an "array index" subscript flag
  2018-06-08  6:15     ` dana
@ 2018-06-08  6:27       ` Michael Milton
  0 siblings, 0 replies; 6+ messages in thread
From: Michael Milton @ 2018-06-08  6:27 UTC (permalink / raw)
  To: dana, zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1173 bytes --]

Ah thanks for clarifying that. I think we're all on the same page.


I... tried to investigate this, but I've only got as far as finding the SCANPM_WANTKEYS constant, which seems relevant. Not really sure where the actual lookup is implemented.

________________________________
From: dana <dana@dana.is>
Sent: Friday, 8 June 2018 4:15:13 PM
To: zsh-workers@zsh.org
Cc: Michael Milton
Subject: Re: Implement an "array index" subscript flag

On 8 Jun 2018, at 00:46, Michael Milton <michael.milton@unimelb.edu.au> wrote:
>This produces no output:
>arr=([1]=a [2]=b)
>keys=${arr[(k)@]}
>echo $keys

You're talking about the (k) subscript flag; i meant the (k) expansion flag. See
the hypothetical example in my earlier reply for how the latter works (just use
an association instead of an array). The former isn't relevant here (array
indexes aren't useful as patterns anyway), but it works like this:

  % local -A assoc=( 'a*' val1 '*a' val2 )
  % print ${assoc[(k)abc]}
  val1
  % print ${assoc[(k)cba]}
  val2

If the (k) expansion flag were made to work on indexed arrays it would
definitely not need to do any pattern matching.

dana


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Implement an "array index" subscript flag
  2018-06-08  5:16 ` dana
  2018-06-08  5:46   ` Michael Milton
@ 2018-06-08  8:25   ` Peter Stephenson
  1 sibling, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2018-06-08  8:25 UTC (permalink / raw)
  To: zsh-workers

On Fri, 8 Jun 2018 00:16:20 -0500
dana <dana@dana.is> wrote:
> On 7 Jun 2018, at 20:37, Michael Milton
> <michael.milton@unimelb.edu.au> wrote:
> >A useful feature for zsh would be the ability to convert an array
> >into an array of keys/indexes for that array.... Bash has a syntax
> >for this, with the ${!array[@]} expansion  
> 
> zsh actually has the (k) flag for this, but it only works on
> associations.
> 
> I feel like the intuitive thing would be for (k) and (v) to work on
> arrays equivalently to the way they work on associations.

This is reasonable, as far as I can see, but the reason this isn't
an issue in zsh is that unlike bash arrays are really arrays --- in
bash they're basically linked lists, so stored sparsely.  So in zsh
the simple {1..${#array}} is good enough.  "Empty" array elements
in the middle contain a zero length string.  If you really need
sparse storage you have to use an associative array.

pws


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-06-08  8:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-08  1:37 Implement an "array index" subscript flag Michael Milton
2018-06-08  5:16 ` dana
2018-06-08  5:46   ` Michael Milton
2018-06-08  6:15     ` dana
2018-06-08  6:27       ` Michael Milton
2018-06-08  8:25   ` Peter Stephenson

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).