0

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!

8
  • so you just want to remove all the 'X's? Commented Oct 30, 2017 at 11:55
  • 2
    Strings don't have any remove method, because strings are immutable. Your first attempt didn't work because it's trying to call a method that doesn't exist. Commented Oct 30, 2017 at 11:56
  • 2
    why not just decoded = garbled.replace('X', '')? Commented Oct 30, 2017 at 11:56
  • What happens if there is an "X" you want to keep? Commented Oct 30, 2017 at 11:58
  • As you're new to Python, you really should be using Python 3 now... all evidecne points out that you're using Python 2... Commented Oct 30, 2017 at 12:16

5 Answers 5

5

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!'
Sign up to request clarification or add additional context in comments.

2 Comments

FYI, joins are more efficient with lists, i.e. ''.join([i for i in garbled if i != 'X']) but I can't find the post right now.
@timgeb True, but most of the time the difference is too small to notice (especially a string as small as in the original question). It's probably not worth the visual clutter unless the performance becomes a problem.
1

filter(function, iterable) does the following procedure:

  1. Go through the elements in iterable (i.e. the second parameter) one at a time.
  2. For each one of those elements, call function (i.e. 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.

Comments

1

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!'

Comments

1
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)

1 Comment

Thank you for the elegant explanation remove() cannot be used in string type.
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.