bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: zsh style associative array assignment bug


From: Ilkka Virta
Subject: Re: zsh style associative array assignment bug
Date: Mon, 29 Mar 2021 12:48:00 +0300

On Mon, Mar 29, 2021 at 1:56 AM Greg Wooledge <greg@wooledge.org> wrote:

> Python is different:
>
> >>> y = ["a", "b", "c", "d"]
> >>> dict(zip(y[::2], y[1::2]))
> {'a': 'b', 'c': 'd'}
> >>> x = ["a", "b", "c"]
> >>> dict(zip(x[::2], x[1::2]))
> {'a': 'b'}
>
> It seems to discard the last (unmatched) value.  Also, dear gods, what
> is that horrible syntax they forced me to google for... and it took MANY
> tries to find it, too.
>

That's a bit different, since it's not really a built-in feature but doing
it manually,
just using some rather terse syntax and tersely named functions. Apart from
Python
having such stuff available, it's not really unlike just filling an
associative array from
an indexed one with a loop in the shell.  And if you do it manually, you
can do
anything you like. You can't do it directly in Python the same way as in
Zsh, Bash or
Perl, though.

[ more Python follows, ignore if you like ]

Just dropping a list to dict() would probably be the most direct
equivalent, but it
doesn't work:

>>> dict([ "a", "b", "c", "d" ])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #0 has length 1; 2 is
required

You have to pair the elements up (which is what zip() does there):

>>> dict([ ("a", "b"), ("c", "d") ])
{'a': 'b', 'c': 'd'}

And you can't leave unpaired elements (or sets of three):

>>> dict([ ("a", "b"), ("c",) ])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #1 has length 1; 2 is
required


Using 'itertools.zip_longest' like Andreas showed would be another
alternative for
doing it manually. It would generate explicit 'None's to fill the shorter
list, which then
would appear in the result. Of course, that's possible because Python has
'None' to
begin with, like Perl has 'undef'. The shell doesn't really have the
equivalent of that.
IMO, an unset value would be the nearest equivalent (vs. an empty string
being an
explicitly defined value), but I guess that's arguable.



I'm not sure what you meant as the horrible syntax, and you probably don't
want to
know this, :) but the index in x[1::2] takes every other element of 'x',
starting at 1.
Somewhat similarly to a brace expansion like {1..9..2}. The zip() there
pairs the
even and odd halves together.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]