简体   繁体   English

Python 过滤器没有按预期工作

[英]Python filter doesn't work as expected

I have the following Python code:我有以下 Python 代码:

a = [1,2,3,'4','55',6]
filter(int,a)

The output is: output 是:

[1, 2, 3, '4', '55', 6]

filter() is supposed to remove the elements from the provided sequence which translate into false, and return only those elements which translate into true. filter()应该从提供的序列中删除转换为 false 的元素,并仅返回那些转换为 true 的元素。

I expected the output to be:我预计 output 是:

[1,2,3,6]

since these are the only integers in my list.因为这些是我列表中唯一的整数。 Am I missing something essential?我错过了一些重要的东西吗?

Use isinstance instead: 使用isinstance代替:

>>> a =[1,2,3,'4','55',6]
>>> filter(lambda x: isinstance(x, int),a)
[1, 2, 3, 6]

int will convert each object to integer and since all numbers/strings on the list are non-zero filter picks them all since they evaluate True in boolean context. int会将每个对象转换为整数,并且由于列表中的所有数字/字符串均为非零,因此filter会将其全部选中,因为它们在布尔上下文中的值为True Instead of that it seems that your goal is to pick objects that are already ints and that can be done with isinstance . 取而代之的是,您的目标似乎是选择已经是int且可以使用isinstance完成的对象。

filter() calls the callable that it is given ( int ) with each item in the iterable and returns those that are Truthy. filter()调用iterable中的每一项赋予其( int )的可调用对象,并返回那些为Truthy的对象。 Since int('56') results in 56 , it is Truthy and is included in the results. 由于int('56')结果为56 ,因此它是Truthy并包含在结果中。 You may want something like this: 您可能想要这样的东西:

filter(lambda x: isinstance(x, int), a)

or better: 或更好:

[x for x in a if isinstance(x, int)]

I agree with @niemmi's and @zondo's solution ie 我同意@niemmi和@zondo的解决方案,即

filter(lambda x: isinstance(x, int), a)

Now the question is why filter(int, a) didn't work ? 现在的问题是为什么filter(int,a)不起作用?

Filter ultimately call function(val) and if this returns false then it filtered it out. 过滤器最终调用function(val) ,如果返回false,则将其过滤掉。

>>> int('4')  # Which is returning 4, and its true.
4

But if you call this, 但是如果你这样称呼

>>> a =[1,2,3,'4','0',6]
>>> filter(int, a)
[1,2,3,4,6]

>>> a =[1,2,3,'4','55a',6]
>>> filter(int, a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '55a'

Try this: 尝试这个:

[x for x in a if isinstance(x, int)]

or 要么

filter(lambda x: isinstance(x, int), a)

A bit longer way:更长一点的方式:

  • We create a function within which we create a child function.我们创建一个 function,在其中创建一个子 function。

  • The first function that is "isins" will take function called inside filter ie isinstance as an input.作为“isins”的第一个 function 将采用称为内部过滤器即isinstance的 function 作为输入。

  • The code then see that it's returning check function and replace isins(isinstance) with check.然后代码看到它正在返回支票function 并将isins(isinstance)替换为支票。

  • Inside child function there is a check for 'True' and 'False' explicitly as bool 1 and 0 are treated in same was as True and Flase hence if we remove this filter then the list will contain numbers as well as bool values and if we put bool filter then 1's and 0's will also get filtered out.在 child function 内部,有一个明确的“True”和“False”检查,因为 bool 1 和 0 被视为与 True 和 Flase 相同,因此如果我们删除这个过滤器,那么列表将包含数字和 bool 值,如果我们放入 bool 过滤器,然后 1 和 0 也将被过滤掉。

  • Ultimately we do the check of func/isinstance to return only those values that are either int or float.最后,我们检查 func/isinstance 以仅返回那些 int 或 float 的值。

     def isins(func): def check(a): if str(a) not in ('True','False'): return (func(a,(int,float))) return check num_list = list(filter(isins(isinstance),a)) num_list
  • Below code also lets you input datatype explicitly.下面的代码还允许您显式输入数据类型。

     def isins(func,dt): def check(a): if str(a) not in ('True','False'): return (func(a,dt)) return check num_list = list(filter(isins(isinstance,(int,float)),a)) num_list

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

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