Most Pythonique, Efficient, Compact, Elegant Way to Do This ... ?

Comments

29 comments posted
Only because nobody else mentioned it...
Only because nobody else mentioned it, a solution using partial application. Probably not the best thing in this situation, but useful to have in your toolset:
  from functools import partial
  from operator import add

  result = map(partial(add, '-c '), k)
Posted by John Lenton (not verified) on Mon, 05/03/2010 - 02:05
Naive solution

Go with the one that is easiest to read. That would be the so-called "naive solution" as it is perfectly clear what is going on and uses very common python idioms. Many of the other methods require more time to study in order to understand their purpose and function. So you are obfuscating the code and making it more difficult to read and debug for .. what? To be clever? I say that, unless you can demonstrate a clear and significant speed advantage to any of the other methods, use the one that optimizes for easy reading and programmer time.

Posted by Matthew Perry (not verified) on Sun, 05/02/2010 - 16:59
There should be one and preferably only one obvious way to do it

... but, as the dozens of approaches suggested here demonstrate, sometimes that way may not be so clear or objectively evident.

So far, IMHO, I think that the most concise approach of the many excellent ones proposed is the one using sum, as suggested by number of you:

    sum((['-c', i] for i in k), [])

However, for conciseness and clarity, I think the approach using extend, also as suggested by a number of you, seems to shine:

    for i in k:
        result.extend(('-c', i))

I guess these two solutions in some respects epitomize two of the major programming paradigms supported by Python, and which comes across as more Pythonic depends on which programming paradigm we are currently most comfortable with.

Posted by Jeet Sukumaran on Sun, 05/02/2010 - 11:51
join and split

['-c'] + ' -c '.join(k).split()

Posted by Anonymous (not verified) on Sun, 05/02/2010 - 11:21
Some solutions


>>> k = ['the quick', 'brown fox', 'jumps over', 'the lazy', 'dog']

>>> ['-c' if i % 2 == 0 else k[(i - 1) / 2] for i in xrange(2 * len(k))]
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

>>> reduce(lambda a, b: a + ['-c', b], k, [])
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

>>> intersperse = lambda a, l: [] if not l else ([a] + l if len(l) == 1 else [a, l[0]] + intersperse(a, l[1:]))
>>> intersperse('-c', k)
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

Posted by Nicolas Trangez (not verified) on Sun, 05/02/2010 - 08:07
Slicing


>>> result = 2*len(k)*["-c"]
>>> result[1::2] = k
>>> result
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

Posted by Peter Otten (not verified) on Sun, 05/02/2010 - 02:59
Most Pythonique, Efficient, Compact, Elegant Way to Do This ...

... is to start by spelling it "pythonic"

:-)

Posted by Paddy3118 (not verified) on Sun, 05/02/2010 - 01:00
Naïveté

For the record, the "naive solution" is very nearly the only one of these that I can read without a pencil and paper to work out the result. I vote naive. :-)

Posted by Brandon Craig Rhodes (not verified) on Sat, 05/01/2010 - 21:58
join() and split()

Another version of join() and split()

>>> '*'.join([ '-c*'+i for i in k]).split('*')
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

I like itertools and extend versions.

Posted by Francisco Palm (not verified) on Sat, 05/01/2010 - 21:32
dot insert
You don't need to mess with creating new lists, or use any external modules.
orig = ['foo', 'bar', 'baz']
for i in xrange(len(orig)):
    orig.insert(i*2, '-c')
Posted by Charlie (not verified) on Sat, 05/01/2010 - 19:06
Can anyone explain the sum() solutions?
I immediately thought of sum() but couldn't get it to do my bidding. Here's the help:
sum(sequence[, start]) -> value

Returns the sum of a sequence of numbers (NOT strings) plus the value
of parameter 'start' (which defaults to 0). When the sequence is
empty, returns start.



So how does this work? It appears to be using [] as the "start" value, which doesn't make any sense to me.
sum((['-c', i] for i in k), [])
(I came up with the extend solution myself.. as x = []; map(x.extend, [('-c', z) for z in k]))

Posted by cory (not verified) on Sat, 05/01/2010 - 17:25
generators
def f(iterable):
    for i in iterable:
        yield '-c'
        yield i
or, more generically, use a weave function
def weave(*iterables):
    iters = map(iter, iterables)
    while 1:
       for it in iters:
           yield it.next()

list(repeat('-c'), k)
weave should be added to itertools IMO
Posted by Simon Davy (not verified) on Sat, 05/01/2010 - 17:10
Using zip

The following also work:

list(itertools.chain(*zip(itertools.repeat('-c'), k)))
list(itertools.chain.from_iterable(zip(itertools.repeat('-c'), k)))

Posted by Ray R (not verified) on Sat, 05/01/2010 - 16:45
Here is another

Here is another one-liner:

result = [x for t in [('-c',i) for i in k] for x in t]

Posted by ss (not verified) on Sat, 05/01/2010 - 16:44
Not sure if it's pythonic,

Not sure if it's pythonic, but this one-liner will do the trick:

result = sum([['-c',i] for i in k], [])

Posted by ss (not verified) on Sat, 05/01/2010 - 16:35
Joining and splitting strings

>>> ('-c|'+'|-c|'.join(k)).split('|')
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

Posted by Esalando Prassi (not verified) on Sat, 05/01/2010 - 16:25
Extend?

>>> result=[]
>>> [result.extend(('-c', x)) for x in k]
[None, None, None, None, None]
>>> result
['-c', 'the quick', '-c', 'brown fox', '-c', 'jumps over', '-c', 'the lazy', '-c', 'dog']

Posted by Esalando Prassi (not verified) on Sat, 05/01/2010 - 16:20
Hi,What about:result =

Hi,
What about:


result = sum([[e, '-c'] for e in k], [])

If we timeit (from timeit import timeit) your two solutions as f1 and f2, and mine as f3, your first solution seems the fastest:

f1: 4.2329611778259277
f2: 8.0269858837127686
f3: 5.8209688663482666

Virtuo

Posted by Virtuo (not verified) on Sat, 05/01/2010 - 16:15
list(flatten(itertools.izip_l

list(flatten(itertools.izip_longest([],k,fillvalue='-c')) )

Posted by Anonymous (not verified) on Sat, 05/01/2010 - 16:12
list(flatten(itertools.izip_l
list(flatten(itertools.izip_longest([],k,fillvalue='-c')) )
Posted by Anonymous (not verified) on Sat, 05/01/2010 - 16:11
flattener

I'd probably use a flattener, although it's not likely to be as fast-

from itertools import izip, repeat
from snakeoil.lists import flatten
result = flatten(izip(repeat('-c'), k))

# snakeoil module being http://pkgcore.org/trac/pkgcore/browser/snakeoil/snakeoil/lists.py

Always kind of wished stdlib had something similar to the iflatten/iflatten_instance functions in there...

Posted by Brian Harring (not verified) on Sat, 05/01/2010 - 16:11
using iPython

using iPython shell
ipython

In [2]: a=['one', 'two', 'three']

In [3]: b = ['-c'] * len(a)

In [4]: b
Out[4]: ['-c', '-c', '-c']

In [5]: l = []

In [6]: [l.extend(i) for i in zip(b, a)]
Out[6]: [None, None, None]

In [7]: l
Out[7]: ['-c', 'one', '-c', 'two', '-c', 'three']

Posted by Anonymous (not verified) on Sat, 05/01/2010 - 16:10
I think that using extend

I think that using extend method in the first case will be more clear

for i in k;
   result.extend(('-c',i))

and you an also do it as a comprehension, if you like...

result = []
[result.extend(('-c', i)) for i in k]

Posted by Jaime (not verified) on Sat, 05/01/2010 - 15:58
another one
Thought of another one:
[j for i in k for j in ['-c', i]]
Posted by Linus (not verified) on Sat, 05/01/2010 - 15:55
To sum lists
Not sure it is the most pythonic, I find it simpler (and it does not use imports) to write:
sum([ ['-c', i] for i in k ], [])
Posted by milosh (not verified) on Sat, 05/01/2010 - 15:53
*zip is Your Friend
Well, here's one that's at least slightly less obscure:

list(itertools.chain(*zip(itertools.repeat("-c"), k)))


Posted by Steve Holden (not verified) on Sat, 05/01/2010 - 15:53
sum((['-c', i] for i in k),
sum((['-c', i] for i in k), [])
Posted by Linus (not verified) on Sat, 05/01/2010 - 15:42
one answer
list(sum(zip(['-c'] * len(k), k), ()))
Posted by Danek Duvall (not verified) on Sat, 05/01/2010 - 15:39
Inserting

If it's okay to change k inserting is another possibility:

for i in range(len(k)-1,-1,-1):k.insert(i, "-c")

Sebastian

Posted by basti (not verified) on Sat, 05/01/2010 - 15:17

Post new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a biological visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.