List comprehension with duplicated function call [duplicate]

 ̄綄美尐妖づ 提交于 2020-06-24 11:23:05

问题


I want to transform a string such as following:

'   1   ,   2  ,    ,   ,   3   '

into a list of non-empty elements:

['1', '2', '3']

My solution is this list comprehension:

print [el.strip() for el in mystring.split(",") if el.strip()]

Just wonder, is there a nice, pythonic way to write this comprehension without calling el.strip() twice?


回答1:


You can use a generator inside the list comprehension:

  [x for x in (el.strip() for el in mylist.split(",")) if x]
#             \__________________ ___________________/
#                                v
#                        internal generator

The generator thus will provide stripped elements, and we iterate over the generator, and only check the truthiness. We thus save on el.strip() calls.

You can also use map(..) for this (making it more functional):

  [x for x in map(str.strip, mylist.split(",")) if x]
#             \______________ ________________/
#                            v
#                           map

But this is basically the same (although the logic of the generator is - in my opinion - better encapsulated).




回答2:


As a simple alternative to get a list of non-empty elements (in addition to previous good answers):

import re

s = '   1   ,   2  ,    ,   ,   3   '
print(re.findall(r'[^\s,]+', s))

The output:

['1', '2', '3']



回答3:


How about some regex to extract all the numbers from the string

import re

a = '   1   ,   2  ,    ,   ,   3   '
print(re.findall(r'\d+', a))

Output:

['1', '2', '3']



回答4:


In just one line of code that's about as terse you're going to get. Ofcourse, if you want to get fanciful you can try the functional approach:

filter(lambda x: x, map(lambda x: x.strip(), mylist.split(',')))

But this gets you terseness in exchange for visibility




回答5:


Go full functional with map and filter by using:

s = '   1   ,   2  ,    ,   ,   3   '
res = filter(None, map(str.strip, s.split(',')))

though similar to @omu_negru's answer, this avoids using lambdas which are arguably pretty ugly but, also, slow things down.

The argument None to filter translates to: filter on truthness, essentially x for x in iterable if x, while the map just maps the method str.strip (which has a default split value of whitespace) to the iterable obtained from s.split(',').

On Python 2, where filter still returns a list, this approach should easily edge out the other approaches in speed.


In Python 3 one would have to use:

res = [*filter(None, map(str.strip, s.split(',')))]

in order to get the list back.




回答6:


If you have imported "re", then re.split() will work:

import re
s='   1   ,   2  ,    ,   ,   3   '
print ([el for el in re.split(r"[, ]+",s) if el])
['1', '2', '3']

If strings separated by only spaces (with no intervening comma) should not be separated, then this will work:

import re
s=' ,,,,,     ,,,,  1   ,   2  ,    ,   ,   3,,,,,4   5, 6   '
print ([el for el in re.split(r"\s*,\s*",s.strip()) if el])
['1', '2', '3', '4   5', '6']



回答7:


List comprehensions are wonderful, but it's not illegal to use more than one line of code! You could even - heaven forbid - use a for loop!

result = []
for el in mystring.split(",")
    x = el.strip()
    if x:
        result.append(x)

Here's a two-line version. It's actually the same as the accepted answer by Willem Van Onsem, but with a name given to a subexpression (and a generator changed to a list but it makes essentially no difference for a problem this small). In my view, this makes it a lot easier to read, despite taking fractionally more code.

all_terms = [el.strip() for el in mystring.split(",")]
non_empty_terms = [x for x in all_terms if x]

Some of the other answers are certainly shorter, but I'm not convinced any of them are simpler/easier to understand. Actually, I think the best answer is just the one in your question, because the repetition in this case is quite minor.



来源:https://stackoverflow.com/questions/47033033/list-comprehension-with-duplicated-function-call

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!