什么是在多个位置切割弦的pythonic方法?

时间:2016-02-27 13:14:00

标签: python string

如果我有一个字符串,比如"The quick brown fox jumps over the lazy dog",并且有一个列表[1, 8, 14, 18, 27]表示在哪里剪切字符串。

我期望得到的是一个包含剪切字符串部分的列表。对于此示例,输出应为:

['T', 'he quic', 'k brow', 'n fo', 'x jumps o', 'ver the lazy dog']

我直观而天真的方法是简单地编写for循环,记住上一个索引,切片并将切片附加到输出。

_str="The quick brown fox jumps over the lazy dog"
cut=[1, 8, 14, 18, 27]
prev=0
out=[]
for i in cut:
    out.append(_str[prev:i])
    prev=i
out.append(_str[prev:])

还有更好的方法吗?

3 个答案:

答案 0 :(得分:11)

这是我将如何做到的:

import matplotlib.pyplot as plt
plt.figure(figsize=(8, 6))
sns.factorplot("MONTH", "VALUE", hue="REGION", data=typessns, kind="box", palette="OrRd"); // OR any plot code

一些解释:

我在前面添加0,在列表末尾添加>>> s = "The quick brown fox jumps over the lazy dog" >>> l = [1, 8, 14, 18, 27] >>> l = [0] + l + [len(s)] >>> [s[x:y] for x,y in zip(l, l[1:])] ['T', 'he quic', 'k brow', 'n fo', 'x jumps o', 'ver the lazy dog'] ,这样

len(s)

给了我一系列切片索引元组。剩下要做的就是在列表解析中解压缩这些索引并生成你想要的切片。

编辑:

如果真的关心此操作的内存占用,因为您经常处理非常大的大字符串和列表,请一直使用生成器并构建列表>>> zip(l, l[1:]) [(0, 1), (1, 8), (8, 14), (14, 18), (18, 27), (27, 43)] 这样它首先包含0和l

对于Python 2:

len(s)

对于Python 3:
>>> from itertools import izip, tee >>> s = "The quick brown fox jumps over the lazy dog" >>> l = [0, 1, 8, 14, 18, 27, 43] >>> >>> def get_slices(s, l): ... it1, it2 = tee(l) ... next(it2) ... for start, end in izip(it1, it2): ... yield s[start:end] ... >>> list(get_slices(s,l)) ['T', 'he quic', 'k brow', 'n fo', 'x jumps o', 'ver the lazy dog'] 执行zip在Python 2中所做的事情(参见Python 3.3版本)

对于使用izip语法的Python 3.3+:

yield from

答案 1 :(得分:1)

递归方法:

def split(cut,str): 
    if cut:
        b=cut.pop()
        return split(cut,str[:b])+[str[b:]]
    return [str] 

答案 2 :(得分:1)

您可以使用生成器功能:

def sli(s, inds):
    it = iter(inds)
    p = next(it)
    yield s[:p]
    for i in it:
        yield s[p:i]
        p = i
    yield s[p:]

print(list(sli(_str, cut)))
['T', 'he quic', 'k brow', 'n fo', 'x jumps o', 'ver the lazy dog']

创建一个可以懒惰评估的切片列表。

除非您需要空字符串列表,否则还需要考虑传递空字符串:

def sli(s, inds):
    if not s:
        return
    it = iter(inds)
    p = next(it)
    yield s[:p]
    for i in it:
        yield s[p:i]
        p = i
    yield s[p:]

除了更强大,使用更少,内存也更快:

Python3:

 l = sorted(random.sample(list(range(5000)), 1000))

 _l = [0] + l + [len(s)]
 [s[x:y] for x,y in zip(_l, _l[1:])]
 ....: 

1000 loops, best of 3: 368 µs per loop

In [39]: timeit list(sli(s, l))
1000 loops, best of 3: 311 µs per loop

Python2:

In [8]: s = "The quick brown fox jumps over the lazy dog"

In [9]: s *= 1000

In [10]: l = sorted(random.sample(list(range(5000)), 1000))

In [11]: %%timeit

_l = [0] + l + [len(s)]
[s[x:y] for x,y in zip(_l, _l[1:])]
....: 
1000 loops, best of 3: 321 µs per loop

In [12]: timeit list(sli(s, l))ched 
1000 loops, best of 3: 204 µs per loop

编写自己的函数是完全pythonic的,在这种情况下比尝试将代码压缩到几行更有效。