Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding two items at a time in a list comprehension

I want to add two items at a time to a list comprehension. One item is constant. How can this be achieved using only one for loop inside of a list comprehension, and no additional functions. Answers that do not use any import will be favored.

Take a look at at the following:

>>> mystring = 'ABCELKJSDLHFWEHSJDHFKHIUEHFSDF'
>>> sum([['^', char] for char in mystring.lower()], [])
['^', 'a', '^', 'b', '^', 'c', '^', 'e', '^', 'l', '^', 'k', '^', 'j', '^', 's', '^', 'd', '^', 'l', '^', 'h', '^', 'f', '^', 'w', '^', 'e', '^', 'h', '^', 's', '^', 'j', '^', 'd', '^', 'h', '^', 'f', '^', 'k', '^', 'h', '^', 'i', '^', 'u', '^', 'e', '^', 'h', '^', 'f', '^', 's', '^', 'd', '^', 'f']

I am trying to make a list with the character ^ prepended before each letter in lower case. In this example, you need to use sum to flatten the list. However, my question is, if it is possible to make a flat list in the first place. The output above is the desired output.

As in, append something constantly before a variable that changes with each iteration of the for loop. One cannot use two for loops here, as that would be too simple, for example:

mystring = 'ABCELKJSDLHFWEHSJDHFKHIUEHFSDF'
print [item for x in mystring.lower() for item in ['^', x]]

If one does something like this:

>>> mystring = 'ABCELKJSDLHFWEHSJDHFKHIUEHFSDF'
>>> [['^', x] for x in mystring]
['^', 'a', '^', 'b', '^', 'c', '^', 'e', '^', 'l', '^', 'k', '^', 'j', '^', 's', '^', 'd', '^', 'l', '^', 'h', '^', 'f', '^', 'w', '^', 'e', '^', 'h', '^', 's', '^', 'j', '^', 'd', '^', 'h', '^', 'f', '^', 'k', '^', 'h', '^', 'i', '^', 'u', '^', 'e', '^', 'h', '^', 'f', '^', 's', '^', 'd', '^', 'f']

You get lists within lists. Thus, is there a way that you can append two items at a time in a list comprehension without have to use an addition for loop or an additional function like sum? I ask this, because its something quite simple, yet I can't find a way to do it. If one tries to do the following:

>>> ['^', x for x in mystring.lower()]
  File "<console>", line 1
    ['^', x for x in mystring.lower()]
              ^
SyntaxError: invalid syntax

The attempt gives a SyntaxError. So, is what I'm asking impossible to do in Python? Using () gives me a list of tuples.

I've also tried using the splat/unpacking operator:

>>> [*['^', x] for x in mystring.lower()]
  File "<console>", line 1
    [*['^', x] for x in mystring.lower()]
     ^
SyntaxError: invalid syntax

But as above, this too is a syntax error. Sorry for this late edit, but I have tried the following:

import itertools
mystring = "HELLOWORLD"
print(list(itertools.chain.from_iterable(('^', x) for x in mystring.lower())))

But the above still required an import.

like image 681
Games Brainiac Avatar asked Oct 19 '13 12:10

Games Brainiac


People also ask

Can we use append in list comprehension?

Using append() to tell Python that each new element should be added to the end is also unnecessary; we don't need to use append() in list comprehension. Instead, we are just defining the variable highest_paid_actors_birthyear and assigning the list comprehension result to that variable.

What is a nested list comprehension?

It is a smart and concise way of creating lists by iterating over an iterable object. Nested List Comprehensions are nothing but a list comprehension within another list comprehension which is quite similar to nested for loops.

Can you add else in list comprehension Python?

Answer. Yes, an else clause can be used with an if in a list comprehension. The following code example shows the use of an else in a simple list comprehension.


2 Answers

You can use itertools.chain.from_iterable, this is equivalent to that nested list comprehension version but slightly efficient(for large lists):

>>> from itertools import chain
>>> mystring = 'ABCELKJSDLHFWEHSJDHFKHIUEHFSDF'
>>> list(chain.from_iterable([['^', x] for x in mystring]))
['^', 'A', '^', 'B', '^', 'C', '^', 'E', '^', 'L', '^', 'K', '^', 'J', '^', 'S', '^', 'D', '^', 'L', '^', 'H', '^', 'F', '^', 'W', '^', 'E', '^', 'H', '^', 'S', '^', 'J', '^', 'D', '^', 'H', '^', 'F', '^', 'K', '^', 'H', '^', 'I', '^', 'U', '^', 'E', '^', 'H', '^', 'F', '^', 'S', '^', 'D', '^', 'F']

In Python 3.3+ you can also use yield from in a generator function:

>>> mystring = 'ABCELKJSDLHFWEHSJDHFKHIUEHFSDF'
>>> def solve(strs):
...     for x in strs:
...         yield from ['^', x]
...         
>>> list(solve(mystring))
['^', 'A', '^', 'B', '^', 'C', '^', 'E', '^', 'L', '^', 'K', '^', 'J', '^', 'S', '^', 'D', '^', 'L', '^', 'H', '^', 'F', '^', 'W', '^', 'E', '^', 'H', '^', 'S', '^', 'J', '^', 'D', '^', 'H', '^', 'F', '^', 'K', '^', 'H', '^', 'I', '^', 'U', '^', 'E', '^', 'H', '^', 'F', '^', 'S', '^', 'D', '^', 'F']
like image 101
Ashwini Chaudhary Avatar answered Oct 17 '22 03:10

Ashwini Chaudhary


You can start with this:

print list( '^'.join(mystring.lower()) )

which gives:

['a', '^', 'b', '^', 'c', '^', ...]

So this would give the desired output:

l = list( '^'.join(mystring.lower()) )
l.insert(0, '^')
print l

And another way:

print [ y for x in zip(['^'] * len(mystring), mystring.lower()) for y in x ]

which gives:

['^', 'a', '^', 'b', '^', 'c', ...
like image 8
perreal Avatar answered Oct 17 '22 04:10

perreal