Anna
Anna

Reputation: 2845

Map Python list element to multiple elements, avoiding nested lists

This way I can build a new list by mapping every element in another list:

# turn [0,5,10,15] into [1,6,11,16]
[ x+1 for x in range(0,20,5) ]

But I want every element to yield two elements in my new lists. How can I do that? Here are my attempts:

# turn [0,5,10,16] into [0,1,-5,6,-10,11,-15,16]
# does not work! gives [[0,1],[-5,6],[-10,11],[-15,16]]
[ [-x,x+1] for x in range(0,20,5) ]

# turn [0,5,10,16] into [0,1,-5,6,-10,11,-15,16]
# does not work! gives [(0,1),(-5,6),(-10,11),(-15,16)]
[ (-x,x+1) for x in range(0,20,5) ]

Of course I could create the list of lists and then flatten it somehow, but is there a neater way?

Upvotes: 1

Views: 1496

Answers (4)

Kasravnd
Kasravnd

Reputation: 107287

You need to use two loop:

>>> [t for x in range(0,20,5) for t in [-x,x+1] ]
[0, 1, -5, 6, -10, 11, -15, 16]

Or if you are dealing with larger data sets you can use itertools.chain()

>>> from itertools import chain
>>> 
>>> list(chain.from_iterable([-x,x+1] for x in range(0,20,5)))
[0, 1, -5, 6, -10, 11, -15, 16]
>>> 

Note that if you just want to iterate over the result you don't have to convert the result to list, because chain.from_iterable returns an iterator and is pretty more optimized in terms of memory usage.

Upvotes: 4

Tadhg McDonald-Jensen
Tadhg McDonald-Jensen

Reputation: 21453

Note that the exact notation you are wanting was proposed but rejected to add to python:

Earlier iterations of this PEP allowed unpacking operators inside list, set, and dictionary comprehensions as a flattening operator over iterables of containers:

>>> ranges = [range(i) for i in range(5)]
>>> [*item for item in ranges]
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]

Using this rejected syntax your case would look like:

[ *(-x,x+1) for x in range(0,20,5) ]

however since list comprehension currently only supports a single element at a time you can simply loop over the additional elements as well:

[ item for x in range(0,20,5)
         for item in (-x,x+1) ]

Upvotes: 0

VHarisop
VHarisop

Reputation: 2826

You could use functools.reduce (no need to import it if you are in Python 2.x):

from functools import reduce

flat_list = reduce(lambda x, y: x + y, [[-x, x+1] for x in range(0, 20, 5)], [])

Or, even better, as @Thrustmaster pointed out:

flat_list = sum(([-x, x+1] for x in range(0, 20, 5)), [])

Upvotes: 0

UltraInstinct
UltraInstinct

Reputation: 44444

To my knowledge, a list comprehension (with one for) can not do more than one element at a time. You can either:

  • flatten it (from itertools import chain)
  • Use a function like below and use that as a generator:

    def myFunc(elements):
        for elem in elements:
            yield -elem
            yield elem + 1
    

Upvotes: 2

Related Questions