简体   繁体   English

嵌套 for 和 if 在列表推导中

[英]nested for and if inside a list comprehension

I have the following code which has for and if alternatively.我有以下代码,其中有 for 和 if 。

lines = ['apple berry Citrus ', 34, 4.46, 'Audi Apple ']

corpus = [ ]

for line in lines:

    # Check if the element is string and proceed
    if isinstance(line, str):

        # Split the element and check if first character is upper case
        for word in line.split():
            if word[0].isupper():
                
                # Append the word to corpus result
                corpus.append(word)
print(corpus)
# Output : ['Citrus', 'Audi', 'Apple']

I am trying to do this in list comprehension but failing.我试图在列表理解中做到这一点,但失败了。 I have tried as below.我已经尝试如下。

# corpus = [  word if word[0].isupper() for word in line.split()  for line in lines if isinstance(line, str)]

How can i achieve this in List Comprehension?我如何在列表理解中实现这一点?

The following will work:以下将起作用:

corpus = [
    word for line in lines if isinstance(line, str) 
         for word in line.split() if word[0].isupper()
]

The scope in nested comprehensions can be confusing at first, but you'll notice that the order of for and if is the same as in the nested loops.嵌套推导中的 scope 一开始可能会令人困惑,但您会注意到forif的顺序与嵌套循环中的顺序相同。

You can do:你可以做:

[word for line in lines if isinstance(line, str) 
     for word in line.split() if word[0].isupper()]

An alternate approach is to prefilter the list lines with filter :另一种方法是使用filter预过滤列表lines

[word for line in filter(lambda e: isinstance(e, str), lines) 
      for word in line.split() if word[0].isupper()]

Or, as pointed out in comments, you can eliminate the lambda with:或者,正如评论中所指出的,您可以使用以下命令消除lambda

[word for line in filter(str.__instancecheck__, lines) 
      for word in line.split() if word[0].isupper()]

Or even two filters:甚至两个过滤器:

[word for line in filter(str.__instancecheck__, lines)
      for word in filter(lambda w: w[0].isupper(), line.split())]

As a general rule, you can take the inner part of the nested loops where you do corpus.append(xxxx) and place it (the xxx) at the beginning of the list comprehension.作为一般规则,您可以将执行 corpus.append(xxxx) 的嵌套循环的内部部分放在列表理解的开头(xxx)。 Then add the nested for loops and conditions without the ':'.然后添加没有“:”的嵌套 for 循环和条件。

corpus = [ word                          # from corpus.append(word)
           for line in lines             # ':' removed ... 
               if isinstance(line,str) 
                   for word in line.split() 
                       if word[0].isupper() ]

# on a single line:
corpus = [ word for line in lines if isinstance(line,str) for word in line.split() if word[0].isupper() ]

print(corpus) # ['Citrus', 'Audi', 'Apple']

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

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