将两个字符串拼接在一起的最pythonic方法是什么?
例如:
输入:
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
输出:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
答案 0 :(得分:126)
对我来说,最pythonic *方式是几乎做同样的事情,但是使用+
运算符来连接每个字符串中的各个字符:
res = "".join(i + j for i, j in zip(u, l))
print(res)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
它比使用两个join()
调用更快:
In [5]: l1 = 'A' * 1000000; l2 = 'a' * 1000000
In [6]: %timeit "".join("".join(item) for item in zip(l1, l2))
1 loops, best of 3: 442 ms per loop
In [7]: %timeit "".join(i + j for i, j in zip(l1, l2))
1 loops, best of 3: 360 ms per loop
存在更快的方法,但它们经常使代码混淆。
注意:如果两个输入字符串不长度相同,那么较长的字符串将被截断,因为 zip
会停止在较短的字符串的末尾迭代。在这种情况下,应该使用zip_longest
模块中的 izip_longest
(Python 2中的 itertools
)代替zip
确保两个字符串完全耗尽。
*从 the Zen of Python 中获取引用:可读性计数。
对我来说,Pythonic = 可读性; i + j
只是在视觉上更容易解析,至少在我看来是这样。
答案 1 :(得分:62)
另一种方式:
res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
print(''.join(res))
输出:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
看起来更快:
%%timeit
res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
''.join(res)
100000 loops, best of 3: 4.75 µs per loop
目前为止最快的解决方案:
%timeit "".join(list(chain.from_iterable(zip(u, l))))
100000 loops, best of 3: 6.52 µs per loop
也适用于较大的字符串:
l1 = 'A' * 1000000; l2 = 'a' * 1000000
%timeit "".join(list(chain.from_iterable(zip(l1, l2))))
1 loops, best of 3: 151 ms per loop
%%timeit
res = [''] * len(l1) * 2
res[::2] = l1
res[1::2] = l2
''.join(res)
10 loops, best of 3: 92 ms per loop
Python 3.5.1。
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijkl'
zip()
)min_len = min(len(u), len(l))
res = [''] * min_len * 2
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
print(''.join(res))
输出:
AaBbCcDdEeFfGgHhIiJjKkLl
itertools.zip_longest(fillvalue='')
当量)min_len = min(len(u), len(l))
res = [''] * min_len * 2
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
res += u[min_len:] + l[min_len:]
print(''.join(res))
输出:
AaBbCcDdEeFfGgHhIiJjKkLlMNOPQRSTUVWXYZ
答案 2 :(得分:47)
使用var obj = [{
Primary: "Hejrwe",
TestVal: "234723",
TestTool: [{
label: 'xyz',
num: '23'
}, {
label: "",
num: ""
}, {
label: "",
num: ""
}],
TestItv: [{
label: 'xyz',
num: '23'
}, {
label: "",
num: ""
}, {
label: "",
num: ""
}]
}, {
Primary: "Urwhe",
TestVal: "32432",
TestTool: [{
label: 'abc',
num: '24'
}, {
label: "",
num: ""
}, {
label: "",
num: ""
}],
TestItv: [{
label: 'abc',
num: '24'
}, {
label: "",
num: ""
}, {
label: "",
num: ""
}]
}];
Object.keys(obj).map(function(index) {
var val = obj[index].TestTool;
var temp = [];
for (var i in val) {
if (val[i].label == "") {
delete val[i].label;
}
if (val[i].num == "") {
delete val[i].num;
}
}
});
console.log(obj);
和join()
。
zip()
答案 3 :(得分:18)
在Python 2上,通过 far 更快的方式做事,大约是小字符串列表切片速度的3倍,长字符串大约30倍,
res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)
但这不适用于Python 3。你可以实现像
这样的东西res = bytearray(len(u) * 2)
res[::2] = u.encode("ascii")
res[1::2] = l.encode("ascii")
res.decode("ascii")
但到那时你已经失去了对小字符串列表切片的收益(它仍然是长字符串速度的20倍),这甚至不适用于非ASCII字符。
FWIW,如果你 在大量字符串上执行此操作并且需要每个周期,和由于某种原因必须使用Python字符串...这里是如何做到的:
res = bytearray(len(u) * 4 * 2)
u_utf32 = u.encode("utf_32_be")
res[0::8] = u_utf32[0::4]
res[1::8] = u_utf32[1::4]
res[2::8] = u_utf32[2::4]
res[3::8] = u_utf32[3::4]
l_utf32 = l.encode("utf_32_be")
res[4::8] = l_utf32[0::4]
res[5::8] = l_utf32[1::4]
res[6::8] = l_utf32[2::4]
res[7::8] = l_utf32[3::4]
res.decode("utf_32_be")
特殊套管较小型的常见情况也会有所帮助。 FWIW,这只是长字符串列表切片速度的3倍,而小字符串则是4到5 慢的因素。
无论哪种方式,我都更喜欢join
解决方案,但由于在其他地方提到时间,我想我也可以加入。
答案 4 :(得分:16)
如果您想要最快的方式,可以将itertools与operator.add
结合使用:
In [36]: from operator import add
In [37]: from itertools import starmap, izip
In [38]: timeit "".join([i + j for i, j in uzip(l1, l2)])
1 loops, best of 3: 142 ms per loop
In [39]: timeit "".join(starmap(add, izip(l1,l2)))
1 loops, best of 3: 117 ms per loop
In [40]: timeit "".join(["".join(item) for item in zip(l1, l2)])
1 loops, best of 3: 196 ms per loop
In [41]: "".join(starmap(add, izip(l1,l2))) == "".join([i + j for i, j in izip(l1, l2)]) == "".join(["".join(item) for item in izip(l1, l2)])
Out[42]: True
但合并izip
和chain.from_iterable
再次更快
In [2]: from itertools import chain, izip
In [3]: timeit "".join(chain.from_iterable(izip(l1, l2)))
10 loops, best of 3: 98.7 ms per loop
之间也存在很大差异
chain(*
和chain.from_iterable(...
。
In [5]: timeit "".join(chain(*izip(l1, l2)))
1 loops, best of 3: 212 ms per loop
没有带连接的生成器这样的东西,传递一个总是会变慢,因为python将首先使用内容构建一个列表,因为它对数据进行了两次传递,一个用于计算所需的大小,一个实际上进行使用生成器无法实现的连接:
/* Here is the general case. Do a pre-pass to figure out the total
* amount of space we'll need (sz), and see whether all arguments are
* bytes-like.
*/
此外,如果您有不同的长度字符串并且您不想丢失数据,则可以使用izip_longest:
In [22]: from itertools import izip_longest
In [23]: a,b = "hlo","elworld"
In [24]: "".join(chain.from_iterable(izip_longest(a, b,fillvalue="")))
Out[24]: 'helloworld'
对于python 3,它被称为zip_longest
但对于python2,veedrac的建议是迄今为止最快的:
In [18]: %%timeit
res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)
....:
100 loops, best of 3: 2.68 ms per loop
答案 5 :(得分:12)
您也可以使用map
和operator.add
执行此操作:
from operator import add
u = 'AAAAA'
l = 'aaaaa'
s = "".join(map(add, u, l))
<强>输出强>:
'AaAaAaAaAa'
第一个可迭代u
中的每个元素和第二个可迭代l
中的第一个元素需要什么映射,并应用作为第一个参数add
提供的函数。然后加入就加入了他们。
答案 6 :(得分:9)
吉姆的答案很棒,但如果您不介意几种进口,这里是我最喜欢的选择:
from functools import reduce
from operator import add
reduce(add, map(add, u, l))
答案 7 :(得分:7)
很多这些建议都假设字符串长度相等。也许这涵盖了所有合理的用例,但至少在我看来,你似乎也想要容纳不同长度的字符串。或者我是唯一一个认为网格应该像这样工作的人:
u = "foobar"
l = "baz"
mesh(u,l) = "fboaozbar"
执行此操作的一种方法如下:
def mesh(a,b):
minlen = min(len(a),len(b))
return "".join(["".join(x+y for x,y in zip(a,b)),a[minlen:],b[minlen:]])
答案 8 :(得分:5)
我喜欢使用两个for
,变量名称可以提示/提醒正在发生的事情:
"".join(char for pair in zip(u,l) for char in pair)
答案 9 :(得分:4)
只是添加另一种更基本的方法:
st = ""
for char in u:
st = "{0}{1}{2}".format( st, char, l[ u.index( char ) ] )
答案 10 :(得分:3)
可能比当前领先的解决方案更快更短:
from itertools import chain
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
res = "".join(chain(*zip(u, l)))
战略速度方面是尽可能多地在C级做。同样的zip_longest()修复了不均匀的字符串,它会出现在与chain()相同的模块中,所以不能在那里给我太多的点数!
我提出的其他解决方案:
res = "".join(u[x] + l[x] for x in range(len(u)))
res = "".join(k + l[i] for i, k in enumerate(u))
答案 11 :(得分:3)
感觉有点不智能,不考虑这里的双列表理解答案,用O(1)努力处理n字符串:
"".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)
其中all_strings
是您要交错的字符串列表。在您的情况下,all_strings = [u, l]
。完整使用示例如下所示:
import itertools
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
b = 'abcdefghijklmnopqrstuvwxyz'
all_strings = [a,b]
interleaved = "".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)
print(interleaved)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
像许多答案一样,最快?可能不是,但简单而灵活。此外,没有太多增加的复杂性,这比接受的答案略快(通常,字符串添加在python中有点慢):
In [7]: l1 = 'A' * 1000000; l2 = 'a' * 1000000;
In [8]: %timeit "".join(a + b for i, j in zip(l1, l2))
1 loops, best of 3: 227 ms per loop
In [9]: %timeit "".join(c for cs in zip(*(l1, l2)) for c in cs)
1 loops, best of 3: 198 ms per loop
答案 12 :(得分:3)
您可以使用iteration_utilities.roundrobin
1
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
from iteration_utilities import roundrobin
''.join(roundrobin(u, l))
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
或同一个包中的ManyIterables
类:
from iteration_utilities import ManyIterables
ManyIterables(u, l).roundrobin().as_string()
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
1这来自我写的第三方库:iteration_utilities
。
答案 13 :(得分:2)
我会使用zip()来获得一种可读且简单的方法:
result = ''
for cha, chb in zip(u, l):
result += '%s%s' % (cha, chb)
print result
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'