Firstly, become accustomed to list comprehensions:
>>> strs = ['1234', 'hello', '6787']
>>> [s for s in strs if s.isalpha()]
['hello']
They are the most adaptable and in most cases, the most readable way of doing this. Then why would you use map
? map
is fast and good looking for simple cases:
>>> map(str.upper, strs)
['1234', 'HELLO', '6787']
But the instance you have to use lambda
, map becomes ugly and slow. This rule also applies for filter
.
In [1]: strs = ['1234', 'hello', '6787']
In [2]: %timeit map(lambda s: s[0] if s.isalpha() else s, strs)
1000000 loops, best of 3: 1.48 us per loop
In [3]: %timeit [s[0] if s.isalpha() else s for s in strs]
1000000 loops, best of 3: 799 ns per loop
Many people have suggested
>>> filter(lambda s: s.isalpha(), strs)
['hello']
But remember lambda s: s.isalpha()
is just fluff for str.isalpha
, the method of the string class.
>>> filter(str.isalpha, strs)
['hello']
This makes it clean and fast to use filter
here, but remember the consequences once you involve lambda
s.
Implementation detail of Python 2.x
Unfortunately python 2.x has two different string types (In python 3 there is only str
which is unicode) str
and unicode
. Therefore the clean solution using str.isalpha
won't work. You could simply change this to unicode.isalpha
but if you are mixing unicode
and str
you need something cross compatible.
One alternative is to use methodcaller
>>> strs = [u'\n', u'test', u'\t']
>>> from operator import methodcaller
>>> filter(methodcaller('isalpha'), strs)
[u'test']
But this isn't very straightforward, that's why it's nice to just use list comprehensions to avoid this trouble.
>>> [s for s in strs if s.isalpha()]
[u'test']