Suppose I have a list:
l=['a','b','c']
And its suffix list:
l2 = ['a_1', 'b_1', 'c_1']
I'd like the desired output to be:
out_l = ['a','a_1','b','b_2','c','c_3']
The result is the interleaved version of the two lists above.
I can write regular for
loop to get this done, but I'm wondering if there's a more Pythonic way (e.g., using list comprehension or lambda) to get it done.
I've tried something like this:
list(map(lambda x: x[1]+'_'+str(x[0]+1), enumerate(a)))
# this only returns ['a_1', 'b_2', 'c_3']
Furthermore, what changes would need to be made for the general case i.e., for 2 or more lists where l2
is not necessarily a derivative of l
?
A very simple solution:
yield
You can use a generator for an elegant solution. At each iteration, yield twice—once with the original element, and once with the element with the added suffix.
The generator will need to be exhausted; that can be done by tacking on a
list
call at the end.You can also re-write this using the
yield from
syntax for generator delegation:If you're on versions older than python-3.6, replace
f'{x}_{i}'
with'{}_{}'.format(x, i)
.Generalising
Consider a general scenario where you have N lists of the form:
Which you would like to interleave. These lists are not necessarily derived from each other.
To handle interleaving operations with these N lists, you'll need to iterate over pairs:
Sliced
list.__setitem__
I'd recommend this from the perspective of performance. First allocate space for an empty list, and then assign list items to their appropriate positions using sliced list assignment.
l
goes into even indexes, andl'
(l
modified) goes into odd indexes.This is consistently the fastest from my timings (below).
Generalising
To handle N lists, iteratively assign to slices.
zip
+chain.from_iterable
A functional approach, similar to @chrisz' solution. Construct pairs using
zip
and then flatten it usingitertools.chain
.iterools.chain
is widely regarded as the pythonic list flattening approach.Generalising
This is the simplest solution to generalise, and I suspect the most efficient for multiple lists when N is large.
Performance
Let's take a look at some perf-tests for the simple case of two lists (one list with its suffix). General cases will not be tested since the results widely vary with by data.
Functions
Software
System—Mac OS X High Sierra—2.4 GHz Intel Core i7
Python—3.6.0
IPython—6.2.1
You could use
zip
:Output:
You can use a list comprehension like so:
Output:
Optional, shorter method:
If you wanted to return
[["a","a_1"],["b","b_2"],["c","c_3"]]
you could writeThis isn't what you want, instead you want
["a","a_1"]+["b","b_2"]+["c","c_3"]
. This can be made from the result of the operation above usingsum()
; since you're summing lists you need to add the empty list as an argument to avoid an error. So that givesI don't know how this compares speed-wise (probably not well), but I find it easier to understand what's going on than the other list-comprehension based answers.
Here's my simple implementation