Python Forum
need 2x elements in list comprehension
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
need 2x elements in list comprehension
#1
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.
Reply
#2
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.
Reply
#3
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'), ())
Reply
#4
(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']
Reply
#5
@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.
Reply
#6
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.
Reply
#7
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')]
Reply
#8
(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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  unable to remove all elements from list based on a condition sg_python 3 453 Jan-27-2024, 04:03 PM
Last Post: deanhystad
  List Comprehension Issue johnywhy 5 543 Jan-14-2024, 07:58 AM
Last Post: Pedroski55
Question mypy unable to analyse types of tuple elements in a list comprehension tomciodev 1 487 Oct-17-2023, 09:46 AM
Last Post: tomciodev
  Using list comprehension with 'yield' in function tester_V 5 1,261 Apr-02-2023, 06:31 PM
Last Post: tester_V
  Checking if a string contains all or any elements of a list k1llcod3 1 1,112 Jan-29-2023, 04:34 AM
Last Post: deanhystad
  How to change the datatype of list elements? mHosseinDS86 9 2,007 Aug-24-2022, 05:26 PM
Last Post: deanhystad
  list comprehension 3lnyn0 4 1,426 Jul-12-2022, 09:49 AM
Last Post: DeaD_EyE
  ValueError: Length mismatch: Expected axis has 8 elements, new values have 1 elements ilknurg 1 5,163 May-17-2022, 11:38 AM
Last Post: Larz60+
  List comprehension used differently coder_sw99 3 1,736 Oct-03-2021, 04:12 PM
Last Post: coder_sw99
  Why am I getting list elements < 0 ? Mark17 8 3,168 Aug-26-2021, 09:31 AM
Last Post: naughtyCat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020