Reputation: 13
L = [[5, 0, 6], [7, 22], [0, 4, 2], [9, 0, 45, 17]]
I do have this list and my task is to remove the 0
's. I have to use both map()
and filter()
function.
The hint is that this task is solvable with a single expression using map, filter and lambda expressions.
I have been trying to figure this out for quite a while but I just don't get it. You don't have to solve it completely, but help would be appreciated.
I assume I use map()
to iterate over the outer lists, but how do I call filter()
with the sublist?
L2 = map(lambda x: filter(lambda x: x<>0 ,L),L)
Upvotes: 1
Views: 1761
Reputation: 87084
You can use the fact that if the first argument to filter()
is None
then only those items that are "true" will be retained. 0
is considered false, so 0 will be removed.
A solution can be written like this:
>>> L = [[5, 0, 6], [7, 22], [0, 4, 2], [9, 0, 45, 17]]
>>> map(lambda l: filter(None, l), L)
[[5, 6], [7, 22], [4, 2], [9, 45, 17]]
If you are using Python 3 then you can call list()
on the result of the filter()
and the map()
to get the required list:
>>> map(lambda l: filter(None, l), L)
<map object at 0x7fb34856be80>
>>> list(map(lambda l: list(filter(None, l)), L))
[[5, 6], [7, 22], [4, 2], [9, 45, 17]]
Now that's getting less readable. A list comprehension is probably better.
>>> [[item for item in l if item] for l in L]
[[5, 6], [7, 22], [4, 2], [9, 45, 17]]
Upvotes: 1
Reputation: 54213
The key to me is to think about types, which is a somewhat foreign concept in Python.
map
takes a function and an iterable, and returns an iterable that is the result of applying that function to each element of the iterable argument.
map(f: "some function",
lst: "some iterable") -> "(f(e) for e in lst)"
in this case, the elements of your outer lists are themselves lists! And you're planning to apply the filter
function to each to remove the zeroes. filter
expects a function (that itself expects an element, then returns True
if that element should be in the result, or False
if it should be removed) and a list of those elements.
filter(f: "some_func(e: 'type A') -> Bool",
lst: "some_iterable containing elements of type A") ->
"(e for e in lst if f(e))":
Your filter
function then is just filter(lambda x: x != 0, some_list)
, or lambda sublst: filter(lambda x: x!=0, sublst)
. Apply that in the map
and you'll get:
map(lambda sublst: filter(lambda x: x!=0, sublst), lst)
or
[[x for x in xs if x!=0] xs in xss]
This is much easier to express in Haskell, which deals with map
and filter
much more naturally.
map (filter (/=0)) lst
-- or still with a list comprehension
[[x | x <- xs, x!=0] | xs <- xss]
Upvotes: 1
Reputation: 257
You can use None argument in filter function and do something like
[list(filter(None, i)) for i in a]
Upvotes: 0
Reputation: 117886
Using map
and filter
you could write the following
>>> list(map(lambda i: list(filter(lambda i: i != 0, i)), L))
[[5, 6], [7, 22], [4, 2], [9, 45, 17]]
For what it's worth, I'd prefer a nested list comprehension
>>> [[i for i in j if i != 0] for j in L]
[[5, 6], [7, 22], [4, 2], [9, 45, 17]]
Upvotes: 2