简体   繁体   English

Python 过滤器 function 在 for 循环中

[英]Python filter function in for loop

I got an issue when using filter-function in for loop.在 for 循环中使用过滤器功能时遇到问题。 2 cases are similar, but the result is different: 2例类似,但结果不同:

nums = list(range(1, 15))
nums = filter(lambda x: x % 2 == 0, nums)
nums = filter(lambda x: x % 3 == 0, nums)
nums = filter(lambda x: x % 4 == 0, nums)
print(list(nums))

>>> [12]

and

nums = list(range(1, 15))
for i in range(2, 5):
    nums = filter(lambda x: x % i == 0, nums)
print(list(nums))

>>> [4, 8, 12]

If I convert filter-object to list, the result is correct.如果我将过滤器对象转换为列表,结果是正确的。

nums = list(range(1, 15))
for i in range(2, 5):
    nums = list(filter(lambda x: x % i == 0, nums))
print(nums)

>>> [12] 

Is there any solution using for loop without converting filter object to list in this case?在这种情况下,有没有使用 for 循环而不将过滤器 object 转换为列表的解决方案?

filter returns a generator, which is why you only obtain a list after passing the generator to list() , which takes all the elements generated and returns them in a list. filter返回一个生成器,这就是为什么您在将生成器传递给list()后才获得一个列表的原因,它获取所有生成的元素并将它们返回到一个列表中。

A way to get what you want without filter() and using for :一种无需filter()并使用for即可获得所需内容的方法:

nums = list(range(1, 15))
result = [x for x in nums for i n range(2, 5) if x % i == 0]

This is called a list comprehension and it's very efficient and readable way of constructing a list like this.这被称为列表理解,它是构建这样一个列表的非常有效和可读的方式。

Filter is generator.过滤器是生成器。 Therefore it uses lazy evaluation of expression.因此它使用了表达式的惰性求值。 From documentation:文档:

Variables used in the generator expression are evaluated lazily when the __next__() method is called for the generator object (in the same fashion as normal generators).当为生成器 object 调用__next__()方法时,生成器表达式中使用的变量会被延迟计算(与普通生成器的方式相同)。

It means that lambda expression is evaluated when you call list(nums) because it calls __next__() method under the hood.这意味着在调用list(nums)时会评估 lambda 表达式,因为它在后台调用__next__()方法。

So in your second example it will (I guess) filter 3 times always with divider 4:因此,在您的第二个示例中,它将(我猜)总是使用除法器 4 过滤 3 次:

nums = filter(lambda x: x % 4 == 0)
nums = filter(lambda x: x % 4 == 0)
nums = filter(lambda x: x % 4 == 0)

Maybe that piece of code gives you better understanding.也许那段代码能让你更好地理解。 Notice that expression is evaluated when list() is called.请注意,调用list()时会计算表达式。 As you can see, loop here doesn't change the result.如您所见,此处的循环不会改变结果。 Using variable i makes the difference:使用变量i会有所不同:

nums = list(range(1, 15))
i = 2
nums = filter(lambda x: x % i == 0, nums)
i = 3
nums = filter(lambda x: x % i == 0, nums)
i = 4
nums = filter(lambda x: x % i == 0, nums)
print(list(nums)) # here i==4
### [4, 8, 12]

nums = list(range(1, 50))
for i in range(2, 5):
   nums = filter(lambda x: x % i == 0, nums)
i = 11
print(list(nums)) # here i==11
### [11, 22, 33, 44]

One more solution:另一种解决方案:

def f(x):
   for i in range(2, 5):
      if x % i != 0:
         return False
   return True

nums = list(range(1, 15))
nums = filter(f, nums)
print(list(nums))

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

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