简体   繁体   English

Python列表理解中的附加条件

[英]Additional condition in Python list comprehension

How would you delete all starting empty items form a list using list comprehension without deleting empty elements in the middle of list. 如何使用列表推导从列表中删除所有起始空项目而不删除列表中间的空元素。 This is an example: 这是一个例子:

desc = []
desc.append('')
desc.append('')
desc.append('')
desc.append('line 1')
desc.append('line 2')
desc.append('')
desc.append('')
desc.append('line 3')
filtered = [x for x in desc if x]
filtered
['line 1', 'line 2', 'line 3']

Here is a simple list comprehension that delete all empty items: 这是一个简单的列表理解, 删除所有空项:

filtered = [x for x in desc if x != '']

What I am trying to achieve using list comprehension is something similar to this: 我想用列表理解实现的目标与此类似:

for i in enumerate(desc):
    if desc[0].strip() == '':
        desc.pop(0)

Use itertools.dropwhile : 使用itertools.dropwhile

>>> from itertools import dropwhile

>>> lines = ['', '', 'line1', 'line2', '', '']
>>> list(dropwhile(lambda line: not line, lines))
['line1', 'line2', '', '']

Alternatively to the lambda, you could use operator.not_ , as @JonClements suggests: 除了lambda之外,你可以使用operator.not_ ,因为@JonClements建议:

>>> from operator import not_

>>> list(dropwhile(not_, lines))
['line1', 'line2', '', '']
>>> desc = ['', '', '  ', 'line 1', 'line 2', '', '', 'line 3']
>>> filtered = next(desc[i:] for i in range(len(desc)) if desc[i].strip())
>>> filtered
['line 1', 'line 2', '', '', 'line 3']

The built-in function next will only iterate till it finds non empty element in desc list. 内置的功能next只会重复,直到它找到non empty element desc中列表。 As soon it finds an element it will stop iteration and will return list from that element till the end instead of iterating whole desc list . 一旦找到一个元素,它将停止迭代,并将从该元素返回列表直到结束,而不是迭代whole desc list

>>> help(next)
Help on built-in function next in module __builtin__:

next(...)
    next(iterator[, default])

    Return the next item from the iterator. If default is given and the iterator
    is exhausted, it is returned instead of raising StopIteration.

Other solutions are good. 其他解决方案都很好。 If list comprehension is not necessary then maybe you can try this single line method, 如果没有必要列表理解那么你可以尝试这种单行方法,

>>> desc
['', '', '', 'line 1', 'line 2', '', '', 'line 3']
>>> 
>>> ';'.join(desc).lstrip(';').split(';')
['line 1', 'line 2', '', '', 'line 3']
>>> 

Step 1 - Join all elements of the list by some delimiter 步骤1 - 通过某个分隔符加入列表的所有元素

>>> x = ';'.join(desc)
';;;line 1;line 2;;;line 3'

Step 2 - Strip delimiters from the starting of the string 第2步 - 从字符串的开头剥去分隔符

>>> x = x.lstrip(';')
'line 1;line 2;;;line 3'

Step 3 - Split the string on delimiter to get the output 第3步 - 在分隔符上拆分字符串以获取输出

>>> x.split(';')
['line 1', 'line 2', '', '', 'line 3']

A list comprehension is a nice way to write the creation of a result list only when the decision of which elements to include depend on properties of each sigle element itself. 只有当决定要包含哪些元素取决于每个sigle元素本身的属性时,列表理解才是编写结果列表创建的好方法。

If the condition depends on other factors (eg the position in the result) then probably an explicit loop is more readable instead (and readability is the main point of list comprehensions). 如果条件取决于其他因素(例如结果中的位置),则可能显式循环更具可读性(可读性是列表推导的主要点)。

Examples of good use: 好用的例子:

  • all even numbers of a list 所有偶数的列表
  • all objects with a size bigger than a certain amount 所有尺寸大于一定数量的物体
  • all not empty elements 所有不是空元素

Examples that don't fit well the comprehension concept: 不符合理解概念的例子:

  • first five even number (NOT ok for a comprehension, the "first five" part doesn't depend on each single element) 前五个偶数(不理解,“前五个”部分不依赖于每一个元素)
  • removing empty elements at the beginning of a list (the condition depends on other elements) 删除列表开头的空元素(条件取决于其他元素)
  • unique elements, ie keeping only the first if an element appears multiple times (the decision about an element depends on previous decisions). 唯一元素,即如果元素多次出现则仅保留第一个元素(关于元素的决定取决于先前的决定)。

Of course you can try to abuse the comprehension to do things they were not designed for, but if the result code is less readable than just writing out the algorithm explicitly then there is no reason to do that. 当然,你可以尝试滥用理解来做他们不是为他们设计的东西,但如果结果代码的可读性低于仅仅明确写出算法,那么没有理由这样做。

May be you can just translate what you wrote into list comprehensions 也许你可以将你写的内容翻译成列表推导

filtered = desc[:]
crap = [filtered.pop(0) for i in filtered if filtered[0].strip()==""]

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

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