简体   繁体   中英

lambda and filter in python

I have the following string and I wanna decode by filtering the X's

garbled = "IXXX aXXmX aXXXnXoXXXXXtXhXeXXXXrX sXXXXeXcXXXrXeXt mXXeXsXXXsXaXXXXXXgXeX!XX"

And I would like to filter. I tried the following code

message = filter(lambda x: garbled.remove(x) if x == "X", garbled)

I did not make this way work. I have found this other solution:

message = filter(lambda x: x != "X", garbled)

But I still wonder why did not work the first one. Can I fix it?

(I am new in python btw) thanks!

You can use a generator expression instead of filter

>>> ''.join(i for i in garbled if i != 'X')
'I am another secret message!'

If you wanted to use filter you'd have to change your lambda to

>>> ''.join(filter(lambda x: x != 'X', garbled))
'I am another secret message!'

Cory already fixed your filter .

In my opinion, your problem is handled best by a simple str.replace .

>>> garbled = "IXXX aXXmX aXXXnXoXXXXXtXhXeXXXXrX sXXXXeXcXXXrXeXt mXXeXsXXXsXaXXXXXXgXeX!XX"
>>> garbled.replace('X', '')
'I am another secret message!'
message = filter(lambda x: garbled.remove(x) if x == "X", garbled)

This code doesn't work, because lambda function must be expression.

garbled.remove(x) if x == "X"

This is statement, not a expression. I delete if x=="X" to make an valid expression,

message = filter(lambda x: garbled.remove(x), garbled)

Next, I catch the error "'str' object has no attribute 'remove'". Because type of garbled is string, and there is no attribute that named 'remove' in string type. To use filter function, first argument must be 'predicate' function (that return True or False), and second argument must be iterable-like. OP's second solution satisfies this condition. second argument is string that is iterable (a list of characters), and first argument is a predicate function that takes one character that is supplied from the second argument string)

filter(function, iterable) does the following procedure:

  1. Go through the elements in iterable (ie the second parameter) one at a time.
  2. For each one of those elements, call function (ie the second parameter) on that element and see whether it returns true.
  3. Collect together only those elements where the function returned true, and return a new list of those.

Look at what happens in step 2 if you pass lambda x: garbled.remove(x) if x == "X" for the function parameter: filter() says to itself, "Hmm, if I set x="I" then is garbled.remove(x) if x == "X" true?". It's like you're shouting an instruction at filter() in its second parameter: "hey, please remove all the "X" s". But that's just not the right thing to go there. The requirements are very precise: it must be a function that takes an element and returns a true or false value.

You can do it this way. You have a mistake in lambda-condition. You even do not need string.replace() .

garbled = "IXXX aXXmX aXXXnXoXXXXXtXhXeXXXXrX sXXXXeXcXXXrXeXt mXXeXsXXXsXaXXXXXXgXeX!XX"
f = lambda x: "" if x in "X" else x
message = filter(f, garbled)
"".join(message)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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