1

有几次,当我需要根据某些条件从列表的两端删除一些元素时,我遇到了一个问题。例如,假设我想从列表的两端删除元素,q一旦遇到第一个 0(包括第一个 0)就从位置开始。

例子:

mylist = [1,1,0,1,0,1,2,3,1,5,1,3,1,0,2]

应该变成:

[1,2,3,1,5,1,3,1]

如果我们取q7。所以,我们去第 7 个元素,开始向左走,当遇到第一个 0 时,我们会记住该索引i0并将其切断mylist = mylist[i0+1:]。对右侧重复相同的步骤。

使用这个逻辑,我用两个循环来完成,就像上面描述的那样。但是好像有点绕。有没有更简单的方法来处理这样的任务?

4

3 回答 3

2

就我个人而言,我特别会这样做的方式是向后看零,然后返回索引并适当地调整它以参考您的原始列表。我担心这可能不是很清楚,所以让我告诉你我在代码中的意思:

zero = lambda l: next(i for i,v in enumerate(l) if v==0)
ending_zero = q + zero(mylist[q:])
starting_zero = q - zero(mylist[:q:-1])
return mylist[starting_zero:ending_zero]

或者将其包装在一个函数中并添加一些一般要求(不一定等于零)

def two_directional_slice(original, condition, q):
    condition = lambda l: (i for i,v in enumerate(l) if condition(v)).next()
    ending_condition = q + condition(mylist[q:])
    starting_condition = q - condition(mylist[:q:-1])
    return mylist[starting_condition:ending_condition]

由于它懒惰地评估条件,我认为您通常最好使用它而不是迭代一次,但在最坏的情况下,这将只遍历您的列表一次。

为了彻底起见,以下是您将如何使用最后一个实现来解决第一个问题:

return two_directional_slice(mylist, lambda x: x==0, 7)
于 2013-11-04T00:03:41.530 回答
1

这是一个非常有效的两行解决方案,它使用itertools.takewhile

>>> mylist = [1,1,0,1,0,1,2,3,1,5,1,3,1,0,2]
>>> q = 7
>>>
>>> from itertools import takewhile as tw
>>> list(tw(bool, mylist[q::-1]))[::-1] + list(tw(bool, mylist[q+1:]))
[1, 2, 3, 1, 5, 1, 3, 1]
>>>

这里重要的是0评估为False. 这意味着您可以在数字不相等时“取” 0

于 2013-11-04T01:16:15.120 回答
0

刚想出这个:

[mylist[i] for i in range(len(mylist)) if i==q or (i < q and 0 not in mylist[i:q+1]) or (i > q and 0 not in mylist[q:i+1])]

在我的情况下有效,但不是很普遍......

于 2013-11-04T00:03:07.683 回答