8

I wanted to use lambdas inside for loops to return if certain elements are non-numerical:

strs = ['1234', 'hello', '6787']

I can use a for loop and iterate through each element:

for elem in strs:

and check elem.islpha().

However, is there a way to use lambdas coupled with a for loop to return the word "hello"?

Óscar López
  • 232,561
  • 37
  • 312
  • 386
Max Kim
  • 1,114
  • 6
  • 15
  • 28
  • So it sounds like you have a working solution. Why do you want to use `lambda` expressions? It isn't needed and won't provide anything over a list comprehension, normal for loop, etc. – Jared Jun 14 '13 at 02:13
  • Just for interest, I wanted to understand – Max Kim Jun 14 '13 at 02:22

5 Answers5

17

Try this, it's easy using a list comprehension:

lst =  ['1234', 'hello', '6787']
[x for x in lst if x.isalpha()]
=>  ['hello']

Or if you definitely want to use a lambda:

filter(lambda x: x.isalpha(), lst)
=>  ['hello']

Notice that you'll rarely use lambdas for filtering inside a for loop, it's not idiomatic. The way to go for filtering elements out of a list is using list comprehensions, generator expressions or (less recommended) the filter() built-in function.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • Suppose, my list was `list = [u'\n', u'test', u'\t']` would I need to convert the list entries to strings and then check `.isalpha()`? – Max Kim Jun 14 '13 at 02:20
  • I think if there is space in `test` to `test and some stuff` `.isalpha()` breaks down – Max Kim Jun 14 '13 at 02:35
  • @MaxKim then you should check if `not x.is_number()`, use the function defined in this [question](http://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-in-python) – Óscar López Jun 14 '13 at 02:39
  • Or, could I do x.strip().isalpha()? – Max Kim Jun 14 '13 at 02:40
  • @MaxKim or even better, make sure that your list doesn't contain spaces in the first place. Use [`split()`](http://docs.python.org/2/library/string.html#string.split) in the input string – Óscar López Jun 14 '13 at 02:42
  • 2 ways: `''.join(x.split()).isalpha()` (not sure if this works) and `x.replace(' ','').isalpha()` (this works) – Max Kim Jun 14 '13 at 02:53
4

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 lambdas.

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']
jamylak
  • 128,818
  • 30
  • 231
  • 230
  • (1) `str.isalpha` doesn't return an uppercase copy, that's `str.upper`. :^) (2) `str.isalpha` won't work if the OP has Python 2 unicode strings as suggested in his comment (`[u'\n', u'test', u'\t']`). – DSM Jun 14 '13 at 04:10
  • @DSM I fixed (1), didn't see `2`, I will add that to my answer – jamylak Jun 14 '13 at 04:13
2

If you really need to use lambda, or you are learning functional programming, you can use filter:

>>> filter(lambda x:x.isalpha(), ['123','hello','456'])
['hello']

Using lambda inside a loop makes no sense in your context, since you can call x.isalpha() directly

Jiaming Lu
  • 875
  • 6
  • 20
0

This is probably what you're looking for. You can't use a for loop explicitly, but you can use a generator expression:

check_isalpha = lambda lst: (elem for elem in lst if elem.isalpha())[0]
Rushy Panchal
  • 16,979
  • 16
  • 61
  • 94
0

If what you want is to pull non-numerical items from a list, I don't see the need to use a lambda.

alphas = [item for item in strs if item.isalpha()]
Justin S Barrett
  • 636
  • 4
  • 14