您可以使用生成器来获得优雅的解决方案。在每次迭代中,产生两次——一次使用原始元素,一次使用添加后缀的元素。
发电机需要耗尽;这可以通过在最后添加list 来完成。
def transform(l):
for i, x in enumerate(l, 1):
yield x
yield f'{x}_{i}' # {}_{}'.format(x, i)
您也可以使用 yield from 语法重写此代码以进行生成器委托:
def transform(l):
for i, x in enumerate(l, 1):
yield from (x, f'{x}_{i}') # (x, {}_{}'.format(x, i))
out_l = list(transform(l))
print(out_l)
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
如果您使用的版本早于 python-3.6,请将 f'{x}_{i}' 替换为 '{}_{}'.format(x, i)。
概括
考虑一个一般场景,您有 N 个表单列表:
l1 = [v11, v12, ...]
l2 = [v21, v22, ...]
l3 = [v31, v32, ...]
...
你想交错的。这些列表不一定是相互派生的。
要处理这 N 个列表的交错操作,您需要迭代对:
def transformN(*args):
for vals in zip(*args):
yield from vals
out_l = transformN(l1, l2, l3, ...)
切片list.__setitem__
我会从性能的角度推荐这个。首先为一个空列表分配空间,然后使用切片列表分配将列表项分配到其适当的位置。 l 进入偶数索引,l'(l 已修改)进入奇数索引。
out_l = [None] * (len(l) * 2)
out_l[::2] = l
out_l[1::2] = [f'{x}_{i}' for i, x in enumerate(l, 1)] # [{}_{}'.format(x, i) ...]
print(out_l)
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
这始终是我计时中最快的(如下)。
概括
要处理 N 个列表,请迭代地分配给切片。
list_of_lists = [l1, l2, ...]
out_l = [None] * len(list_of_lists[0]) * len(list_of_lists)
for i, l in enumerate(list_of_lists):
out_l[i::2] = l
一种功能性方法,类似于@chrisz 的解决方案。使用zip 构造对,然后使用itertools.chain 将其展平。
from itertools import chain
# [{}_{}'.format(x, i) ...]
out_l = list(chain.from_iterable(zip(l, [f'{x}_{i}' for i, x in enumerate(l, 1)])))
print(out_l)
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
iterools.chain被广泛认为是pythonic列表展平方法。
概括
这是最简单的泛化解决方案,我怀疑当 N 很大时对多个列表最有效。
list_of_lists = [l1, l2, ...]
out_l = list(chain.from_iterable(zip(*list_of_lists)))
性能
让我们看一下针对两个列表(一个带有后缀的列表)的简单情况的一些性能测试。一般情况下不会进行测试,因为结果因数据而异。
Benchmarking code, for reference.
功能
def cs1(l):
def _cs1(l):
for i, x in enumerate(l, 1):
yield x
yield f'{x}_{i}'
return list(_cs1(l))
def cs2(l):
out_l = [None] * (len(l) * 2)
out_l[::2] = l
out_l[1::2] = [f'{x}_{i}' for i, x in enumerate(l, 1)]
return out_l
def cs3(l):
return list(chain.from_iterable(
zip(l, [f'{x}_{i}' for i, x in enumerate(l, 1)])))
def ajax(l):
return [
i for b in [[a, '{}_{}'.format(a, i)]
for i, a in enumerate(l, start=1)]
for i in b
]
def ajax_cs0(l):
# suggested improvement to ajax solution
return [j for i, a in enumerate(l, 1) for j in [a, '{}_{}'.format(a, i)]]
def chrisz(l):
return [
val
for pair in zip(l, [f'{k}_{j+1}' for j, k in enumerate(l)])
for val in pair
]