Python Forum

Full Version: need 2x elements in list comprehension
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
i'm build a set of options for a command in a list. i have a list of directories to exclude. i have wanted to do this kind of thing many times before. i want to make a list comprehension that has TWO (2) elements for each iteration of the given iterator.

    what = ['ab','bc/de','fg/hi/jk']
    ...
    newlist = [... '--exclude' ... for x in what]
that code should make newlist refer to (for example) ['--exclude','ab','--exclude','bc/de','--exclude','fg/hi/jk']

i can do this in a construction loop like:
    what = ['ab','bc/de','fg/hi/jk']
    ...
    newlist = []
    for x in what:
        newlist.append('--exclude')
        newlist.append(x)
and i end up doing that, or something like it. but i'd like to get this into a one line comprehension that is clear code.
I can't figure a way to do it with list comprehension alone, but this answer on SO provides a similar solution (using itertools.chain.from_iterable), if it helps.
I have done similar things before and never found a nice solution.

In this case there is a dirty solution:
what = ['ab','bc/de','fg/hi/jk']
sum(zip(['--exclude']*len(what), what), ())
But notice that produces a tuple, not a list.

Using itertools is other option... as ugly as the previous:
sum(itertools.zip_longest((), what, fillvalue='--exclude'), ())
(Apr-28-2018, 01:02 AM)Skaperen Wrote: [ -> ]but i'd like to get this into a one line comprehension that is clear code.
What you have is the clearest code for that solution.
@killerrex nice,but as you say ugly and for sure not readable.

Maybe,but still not as clear as couple append lines.
>>> what = ['ab','bc/de','fg/hi/jk']
>>> ' '.join(['--exclude ' + i for i in what]).split()
['--exclude', 'ab', '--exclude', 'bc/de', '--exclude', 'fg/hi/jk']
Dos f-string help,not really Undecided
>>> ' '.join([f'--exclude {i}' for i in what]).split()
['--exclude', 'ab', '--exclude', 'bc/de', '--exclude', 'fg/hi/jk']
@snippsat, The problem of using split is that one of the paths can contain also a space... I have been bitten by this many times.

If it does not matter to be two lines, maybe one of the most expressive ways to achieve this is:
newlist = ['--exclude']*2*len(what)
newlist[1::2] = what
But I do not know if it better than the original proposal.
the OP in the linked stackoverflow page shows what i think is a common train of thought, which is to go from a plain list:

[ a, b, c ]

to a repeated one:

[ a, b, c for n in range(3)]

and expecting the whole list to repeat 3 times, like:

[ a, b, c, a, b, c, a, b, c ]

IMHO, this looks like a reasonable language add on for a future version. and it should be OK for other comprehensions that in plain form use commas for item separation. it's just extending the plain list (where the commas are valid) with the iteration, etc.
Looks like a good idea. It will not interfere with existing code as currently that syntax is illegal.
The proposal looks like a "extend" version of the comprehensions. If currently a list comprehension is equivalent to a for+append loop:
l = [x for x in range(3)]
# Is equivalent to:
l = []
for x in range(3):
    l.append(x)
In this case the syntax will be with extend:
l = ['a', x for x in range(3)]
# Shall be the same as:
l = []
for x in range(3):
    l.extend(('a', x))
So looking to the other comprehensions they will look like:
>>> (x, 'a', x+10 for x in range(3))
(0, 'a', 10, 1, 'a', 11, 2, 'a', 12)

>>> {x: 'a', x+10: 'b' for x in range(3)}
{0: 'a', 10: 'b', 1: 'a', 11: 'b', 2: 'a', 12: 'b'}

>>> {x, x+10 for x in range(3)}
{0, 1, 2, 10, 11, 12}
And it is always possible to obtain a list of tuples as now:
>>> [(x, 'a') for x in range(3)]
[(0, 'a'), (1, 'a'), (2, 'a')]
(Apr-28-2018, 01:34 PM)killerrex Wrote: [ -> ]If it does not matter to be two lines, maybe one of the most expressive ways to achieve this is:
newlist = ['--exclude']*2*len(what)
newlist[1::2] = what
But I do not know if it better than the original proposal.

but, i like it. i still like my suggestion better.

you can use if in a comprehension, so why not for?