简体   繁体   English

以之字形方式连接字符串列表的算法

[英]Algorithm to concatenate a list of strings in zig-zag fashion

I have the following problem: From a list of strings, i have to take the first letters from all the strings, after (from back to front), i have to take the second letters, after the third letters from front to end and so on.我有以下问题:从字符串列表中,我必须从所有字符串中取第一个字母,之后(从后到前),我必须从前到尾取第二个字母,在第三个字母之后等等上。

Example input:示例输入:

['abcd', 'efgh', 'ijkl', 'mnop']

Output should be: Output 应该是:

'aeimnjfbcgkoplhd'

Here I am so far, the first "for" is appending to the array: aeim and cgko the second "for" is appending to the array: njfb and plhd.到目前为止,第一个“for”附加到数组:aeim 和 cgko,第二个“for”附加到数组:njfb 和 plhd。 Anyway the order is not good, i need aeim + njfb + cgko + plhd反正顺序不好,我需要aeim + njfb + cgko + plhd

array = []
if len(list_of_strings[0]) % 2 == 0: # if we have strings with even number of letters
    for j in range(len(list_of_strings[0]/2)): # range(2) in our example
        for i in range(len(list_of_strings)): # range(4) in our example
            array.append(list_of_strings[i][j*2])

    for j in range(1, len(list_of_strings[0]), 2): # range(1, 4, 2) in our example
        for i in range(len(list_of_strings) - 1, -1, -1): # range(3, -1, -1) in our example
            array.append(list_of_strings[i][j])

Please help.请帮忙。

Thank you谢谢

You can use a simple one-liner using "unzip" (ie zip(*a) ) and str.join :您可以使用“解压缩”(即zip(*a)str.join使用简单的单线:

a = ['abcd', 'efgh', 'ijkl', 'mnop']
b = ''.join(''.join(t[::1-2*(i%2)]) for i, t in enumerate(zip(*a)))
assert b == 'aeimnjfbcgkoplhd'

join can take a generator expression as an argument, in this case the generator expression is join可以将生成器表达式作为参数,在这种情况下生成器表达式是

''.join(t[::1-2*(i%2)]) for i, t in enumerate(zip(*a))

The expression表达方式

zip(*a)

unzips the strings in a , ie it returns a generator which yields tuples containing all first letters, all second letters, etc. of each string.解压缩a中的字符串,即它返回一个生成器,该生成器生成包含每个字符串的所有第一个字母、所有第二个字母等的元组。

The indexing in中的索引

t[::1-2*(i%2)]

ensures that we reverse the order of the tuple every 2nd iteration.确保我们在每第二次迭代中反转元组的顺序。


EDIT编辑

I benchmarked my one-liner vs. @cs95's answer , and performance of both is the same within error margins.我将我的单线与@cs95 的答案进行了基准测试,两者的性能在误差范围内是相同的。 I think in "real code" I'd hence prefer his solution for its higher clarity.我认为在“真实代码”中,我更喜欢他的解决方案,因为它更清晰。

Think of the characters as elements in a 2D array:将字符视为二维数组中的元素:

a b c d
e f g h
i j k l
m n o p

We want to go in down on odd columns, then up on even columns, so we do something like this:我们希望 go 在奇数列上向下,然后在偶数列上向上,所以我们这样做:

chars = []
for i in range(len(l[0])):
    for w in l[::1 if i  % 2 == 0 else -1]:  
        chars.append(w[i])
print(''.join(chars))
# aeimnjfbcgkoplhd

l[::1 if i % 2 == 0 else -1] will reverse the list for even columns so we're picking characters from the end. l[::1 if i % 2 == 0 else -1]将反转偶数列的列表,因此我们从末尾挑选字符。 This is intuitive but ugly since slicing the list creates a shallow copy.这是直观但丑陋的,因为对列表进行切片会创建一个浅拷贝。 We can do something a little more clever by using a mod to determine whether to iterate in reverse:我们可以通过使用 mod 来确定是否反向迭代来做一些更聪明的事情:

chars = []
for i in range(len(l[0])):
    for j in range(len(l)) if i % 2 == 0 else reversed(range(len(l))):
        chars.append(l[j][i])
print(''.join(chars))
# aeimnjfbcgkoplhd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM