我需要在包含特定字符串的文本文件中找到一行,然后将该行及其后面的所有行追加到列表中。这就是我完成它的方式..
file1 = open("input.txt", "r")
always_print = False
lines = file1.readlines()
output = []
for line in lines:
if always_print or "def set" in line: #def set is the string i want
output.append(line)
always_print = True
虽然这很好用,但我尝试使用列表推导做同样的事情。这就是我得到的:
lines = [ item.strip() for item in open("input.txt")]
always_print = False
output = [item for item in lines if "def set" or print_always in item]
这显然不起作用,因为当找到所需的字符串时我没有设置always_print = True。我如何在列表理解中做到这一点?
答案 0 :(得分:8)
使用itertools.dropwhile()
查找包含def set
的第一行:
from itertools import dropwhile
output = list(dropwhile(lambda l: 'def set' not in l, lines))
dropwhile()
会跳过lines
中与您的测试不符的任何条目;一旦它匹配就停止测试,并从那里开始简单地产生一切。
dropwhile()
返回一个迭代器;我在这里使用list()
将其转换为行列表,但您也可以将其用作另一个循环的基础,例如剥离换行符等。
演示:
>>> from itertools import dropwhile
>>> lines = '''\
... foo
... bar
... def set():
... spam
... ham
... eggs
... '''.splitlines(True)
>>> list(dropwhile(lambda l: 'def set' not in l, lines))
['def set():\n', ' spam\n', ' ham\n', ' eggs\n']
答案 1 :(得分:2)
编辑更正我之前完全错误的答案:
不是说我会在生产代码中使用它,而是在黑客攻击它,你可以在列表理解中做到这一点......
always_print = []
output = [item for item in lines
if always_print
or (always_print.append(1) if ("def set" in item) else None)
or "def set" in item]
只是为了解释,三个条件中的第二个总是返回None
,这是一个Falsy值。
如果您不想评估"def set" in item
两次,请进一步深入到黑暗中:
always_print = []
output = [item for item in lines
if always_print
or (
(always_print.append(1) or True) if ("def set" in item) else False
)]
<强> EDIT2 强>
如果我更详细地描述这里发生的事情......
上面的代码(以及Kevin在评论中提到的)使用了三个不同的技巧。
False
,任何其他数字为True
。同样,空列表为False
,非空列表为True
。a_list.append(x)
是一个函数调用并返回None
,其被评估为False
}。它还有将新元素x
添加到a_list
末尾的副作用。and
和or
等逻辑运算符从左到右都有评估顺序。 and
在第一个False
值处停止执行,or
在第一个True
值处停止执行,该值可用于控制是否根据某些值执行列表追加条件。三元运算符&#39; x if y else z&#39;也有评估顺序,但评估&#39; y&#39;首先是&#39; x&#39;或者&#39; z&#39;但从来没有。正如您所看到的,一组非常迂回的逻辑技巧可能在超优化的C(或IOCCC)中占有一席之地,但不是Python。 可能可以在列表理解中复制您的控制流,但实际上,每次都使用dropwhile
。
答案 2 :(得分:0)
掉线可能是最好的解决方案。但如果你想要一些非常有趣的东西,请看看以下内容:
使用列表推导可以使用简单的检查和转换,但您应该看到列表推导更像是数学映射。但是,您可以使用您用来测试项目是否应包含某种状态的功能,即如果已经发生某些事情,请检查您的检查。使它成为一个仿函数(或函数对象):
class Drop_before:
def __init__(self, val):
self.val = val
self.always_print = False
def __call__(self, current_val):
if current_val == self.val:
self.always_print = True
return self.always_print
drop_before_6 = Drop_before(6)
print [x for x in xrange(10) if drop_before_6(x)]
#using filter
print filter(Drop_before(4), xrange(10))
输出:
[6, 7, 8, 9]
[4, 5, 6, 7, 8, 9]