列表是否有类似“ strip”的方法?

时间:2019-03-28 06:09:26

标签: python list list-comprehension strip

python中的buildin strip方法可以轻松剥离满足自定义条件的填充子字符串。例如

"000011110001111000".strip("0")

将在字符串的两侧修剪零填充,并返回11110001111

我想为列表找到类似的功能。例如,对于给定列表

input = ["0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "0"]

预期输出将为

output = ["1", "1", "0", "0", "1", "0", "1"]

示例input中的项目过于简化,它们可能是任何其他python对象

list comprehension将删除所有项目,而不是填充项目。

[i for i in input if i != "0"]

5 个答案:

答案 0 :(得分:5)

从两端使用itertools.dropwhile

from itertools import dropwhile

input_data = ["0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "0"]

def predicate(x):
    return x == '0'

result = list(dropwhile(predicate, list(dropwhile(predicate, input_data))[::-1]))[::-1]
result

输出:

['1', '1', '0', '0', '1', '0', '1']

答案 1 :(得分:2)

没有列表方法,但是实现这样的功能并不困难:扫描所需的索引,然后切片到它们。

def strip_seq(predicate, xs):
    def scan(xs):
        return next((i for i, x in enumerate(xs) if not predicate(x)), 0)
    return xs[scan(xs) : -scan(reversed(xs)) or None]

xs = ["0", "0", "a", "1", "0", "0", "1", "0", "b", "0", "0", "0"]
print(strip_seq(lambda x: x=='0', xs))  # ['a', '1', '0', '0', '1', '0', 'b']

这应该适用于任何可切片的序列类型,包括字符串和元组。

答案 2 :(得分:1)

您可以右键单击while / pop。

input = ["0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "0"]
while input and input[-1] == "0": input.pop()

您可以使用itertools.dropwhile左移,但是您可能必须重新创建一个列表。

from itertools import dropwhile
input = [*dropwhile(lambda x: x=='0', input)]

或者您可以通过转换为双端队列从两端高效地进行while / pop操作。

from collections import deque
input = ["0", "0", "1", "1", "0", "0", "1", "0", "1", "0", "0", "0"]
input = deque(input)
while input and input[-1] == '0': input.pop()
while input and input[0] == '0': input.popleft()

(而且input()已经是一个内置函数,因此最好不要将该名称重复用于变量。)

答案 3 :(得分:0)

没有内置方法。您可以使用itertools.dropwhile左移。可以使用生成器功能进行剥离。

import itertools as it
stripleft = list(it.dropwhile(lambda x: x==myitem, inputlist))

答案 4 :(得分:0)

下面给出“基本”解决方案。使用dropwhile的解决方案会反转输入,这在某些情况下可能会很昂贵。

下面的解决方案计算开始和结束索引并返回输入的一部分。

此解决方案适用于其他类型的序列,例如元组,其返回值与输入的类型相同。尽管str.split()可能会更快,但该方法也适用于字符串输入。

def strip_basic(input_data, predicate):
    N = len(input_data)
    if not N:
        return input_data[0:0]      # empty sequence, new copy for mutables
    i = 0
    while i < N and predicate(input_data[i]):
        i = i + 1
    if i == N:                      # optimization
        return input_data[0:0]      # empty sequence
    j = N - 1
    while j and predicate(input_data[j]):
        j = j - 1
    j = j + 1
    return input_data[i:j]

为进行比较(在此解决方案中,一部分输入被反向两次):

def strip_dropwhile(input_data, predicate):
    return list(dropwhile(predicate, list(dropwhile(predicate, input_data))[::-1]))[::-1]

以下是一些使用timeit的数字。请注意,对于病理情况,输入很大,并且没有要输入的元素 去除掉,dropdrop解决方案比基本解决方案慢大约8倍。 在输入较大且所有元素都被剥离的情况下,基本解决方案是 比dropdrop解决方案慢1.9倍。

# input len = 12, output len = 7
# predicate = lambda x: x == '0'; input_data = list('001100101000')

# dropwhile solution:
200000 loops, best of 5: 1.84 usec per loop

# basic solution:
200000 loops, best of 5: 1.51 usec per loop
# input len = 1,000,000, output len = 1,000,000
# predicate = lambda x: x == '0'; input_data = ['1'] * 1000000

# dropwhile solution:
10 loops, best of 5: 29.3 msec per loop

# basic solution:
100 loops, best of 5: 3.58 msec per loop
# input len = 1,000,000, output len = 0
# predicate = lambda x: x == '0'; input_data = ['0'] * 1000000

# dropwhile solution:
5 loops, best of 5: 98 msec per loop

# basic solution:
2 loops, best of 5: 183 msec per loop