Posts: 4,646
Threads: 1,493
Joined: Sep 2016
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.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 1,150
Threads: 42
Joined: Sep 2016
Apr-28-2018, 08:42 AM
(This post was last modified: Apr-28-2018, 08:42 AM by j.crater.)
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.
Posts: 116
Threads: 1
Joined: Apr 2018
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'), ())
Posts: 7,316
Threads: 123
Joined: Sep 2016
Apr-28-2018, 12:52 PM
(This post was last modified: Apr-28-2018, 12:58 PM by snippsat.)
(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
>>> ' '.join([f'--exclude {i}' for i in what]).split()
['--exclude', 'ab', '--exclude', 'bc/de', '--exclude', 'fg/hi/jk']
Posts: 116
Threads: 1
Joined: Apr 2018
@ 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.
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
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.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 116
Threads: 1
Joined: Apr 2018
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')]
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
Apr-30-2018, 02:16 AM
(This post was last modified: Apr-30-2018, 02:18 AM by Skaperen.)
(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 ?
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
|