Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在列表中复制字符串,并向新添加的字符串添加整数后缀_Python_String_List_Performance_Duplicates - Fatal编程技术网

Python 在列表中复制字符串,并向新添加的字符串添加整数后缀

Python 在列表中复制字符串,并向新添加的字符串添加整数后缀,python,string,list,performance,duplicates,Python,String,List,Performance,Duplicates,假设我有一个列表: l = ['a', 'b', 'c'] 及其后缀列表: l2 = ['a_1', 'b_1', 'c_1'] 我希望期望的输出是: out_l = ['a', 'a_1', 'b', 'b_2', 'c', 'c_3'] 结果是上述两个列表的交错版本 我可以为循环编写常规的,以完成此任务,但我想知道是否有更具python风格的方法(例如,使用列表理解或lambda)来完成此任务 我试过这样的方法: list(map(lambda x: x[1]+'_'+str(x[0]

假设我有一个列表:

l = ['a', 'b', 'c']
及其后缀列表:

l2 = ['a_1', 'b_1', 'c_1']
我希望期望的输出是:

out_l = ['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
结果是上述两个列表的交错版本

我可以为循环编写常规的
,以完成此任务,但我想知道是否有更具python风格的方法(例如,使用列表理解或lambda)来完成此任务

我试过这样的方法:

list(map(lambda x: x[1]+'_'+str(x[0]+1), enumerate(a)))
# this only returns ['a_1', 'b_2', 'c_3']

此外,对于一般情况,即对于2个或多个列表,如果
l2
不一定是
l
的派生,则需要进行哪些更改?

您可以使用如下列表理解:

l=['a','b','c']
new_l = [i for b in [[a, '{}_{}'.format(a, i)] for i, a in enumerate(l, start=1)] for i in b]
输出:

['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
可选,较短的方法:

[j for i, a in enumerate(l, 1) for j in [a, '{}_{}'.format(a, i)]]
您可以使用生成器来实现优雅的解决方案。在每次迭代中,生成两次,一次生成原始元素,一次生成添加后缀的元素

发电机需要排气;这可以通过在末尾添加一个
列表
调用来实现

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))

如果您使用的是早于python-3.6的版本,请将
f'{x}{i}'
替换为
'{}{}'。格式(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, ...)

已切片
列表。\uuuu setitem\uuuuuu
从性能的角度来看,我建议这样做。首先为空列表分配空间,然后使用切片列表分配将列表项分配到相应的位置
l
进入偶数索引,
l'
l
modified)进入奇数索引

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) ...]

从我的计时来看,这始终是最快的(见下文)

泛化
要处理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)]))) 

iterools.chain
被广泛认为是pythonic列表扁平化方法

泛化
这是推广的最简单的解决方案,而且我认为当N较大时,对于多个列表最有效

list_of_lists = [l1, l2, ...]
out_l = list(chain.from_iterable(zip(*list_of_lists)))

性能 让我们看一下两个列表(一个带有后缀的列表)的简单情况下的一些性能测试。一般情况下不会进行测试,因为结果因数据而异

功能 您可以使用:

输出:

['a', 'a_1', 'b', 'b_2', 'c', 'c_3']
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']

如果您想返回
[[“a”,“a_1”],[“b”,“b_2”],[“c”,“c_3”]
您可以编写

new_l=[[x,"{}_{}".format(x,i+1)] for i,x in enumerate(l)]
这不是你想要的,而是你想要的
[“a”,“a_1”]+[“b”,“b_2”]+[“c”,“c_3”]
。这可以通过使用
sum()
从上述操作的结果中得出;因为要对列表求和,所以需要将空列表添加为参数以避免错误。这就给了

new_l=sum(([x,"{}_{}".format(x,i+1)] for i,x in enumerate(l)),[])

我不知道这在速度方面如何比较(可能不是很好),但我发现比其他基于列表理解的答案更容易理解发生了什么

l=['a','b','c']
# generate new list with the indices of the original list
new_list=l + ['{0}_{1}'.format(i, (l.index(i) + 1)) for i in l]
# sort the new list in ascending order
new_list.sort()
print new_list
# Should display ['a', 'a_1', 'b', 'b_2', 'c', 'c_3']

一个非常简单的解决方案:

out_l=[]
for i,x in enumerate(l,1):
    out_l.extend([x,f"{x}_{i}"])

对于这个问题,下面是一个更容易理解的列表:

l = ['a', 'b', 'c']
print([ele for index, val in enumerate(l) for ele in (val, val + f'_{index + 1}')])
输出:

['a', 'a_1', 'b', 'b_2', 'c', 'c_3']

注意,这只是交错两个列表的一个更简单的解决方案。这不是多个列表的解决方案。我之所以对
循环使用两个
,是因为在撰写本文时,列表理解不支持元组解包。

您可以使用列表理解而不是zip。不确定哪一个更快…如果你看一下计时,这比使用列表理解更快。要快得多。从可读性、简单性和维护性的角度来看,我建议使用
yield
,因为这不太可能成为主要的瓶颈。(可能数据量不够大,可能不是性能关键型应用。)生成器非常容易理解。OP可以返回并优化,如果它被证明是一个问题+1@user1717828我很高兴你从中学到了一些东西!它们被称为f字符串,是为python-3.6+引入的。请务必查看以了解更多信息。学习愉快!我不明白为什么
会从中产生收益。请您对此进行更多解释,好吗?
yield from
提供了一种更为简洁的语法,可以完成两条
yield
语句所做的事情-它代表了yield过程,因此您不需要在iterable(或本例中的两条yield语句)上编写循环@cs95性能比较有偏差,因为
ajax1234
cs0
使用
str.format
,而其他函数使用的f字符串速度要快得多(
sruthiV
甚至使用
+
)。因此,通过使用性能较低的格式化选项,这些函数的性能会有效降低。为了提供有意义的比较,需要更新函数以使用相同的格式选项。另外,
sruthiV
应该使用
i//2
而不是
int(i/2)
,因为它效率更高(因此避免了额外的偏差)。@cᴏʟᴅsᴘᴇᴇᴅ 为什么不是被问到的?如果
l==['a','b','c']
结果是
['a','a_1','b','b_2','c','c_3']
根据需要,它避免了对
循环使用
。然而,对列表调用sum()通常是不受欢迎的,它比循环更糟糕。相关:和
out_l=[]
for i,x in enumerate(l,1):
    out_l.extend([x,f"{x}_{i}"])
l = ['a', 'b', 'c']
print([ele for index, val in enumerate(l) for ele in (val, val + f'_{index + 1}')])
['a', 'a_1', 'b', 'b_2', 'c', 'c_3']