Given a list:
mylist = [\'dog\', \'cat\', \'mouse_bear\', \'lion_tiger_rabbit\', \'ant\']
I\'d like a one-liner to return a new list:
Since so many answers here were posted (over ten), I thought it'd be beneficial to show some timing stats to compare the different methods posted:
-----------------------------------------
AChampion time: 2.6322
-----------------------------------------
hiro_protagonist time: 3.1724
-----------------------------------------
Eugene_Sh time: 1.0108
-----------------------------------------
cᴏʟᴅsᴘᴇᴇᴅ time: 3.5386
-----------------------------------------
jdehesa time: 2.9406
-----------------------------------------
mogga time: 3.1645
-----------------------------------------
Ajax1234 time: 2.4659
-----------------------------------------
Here's the script I used to test:
from timeit import timeit
setup = """
from itertools import chain
mylist = ['dog', 'cat', 'mouse_bear', 'lion_tiger_rabbit', 'ant']
"""
methods = {
'AChampion': """[animal for word in mylist for animal in word.split('_')]""",
'hiro_protagonist': """list(chain.from_iterable(item.split('_') for item in mylist))""",
'Eugene_Sh': """'_'.join(mylist).split('_')""",
'cᴏʟᴅsᴘᴇᴇᴅ': """list([(yield from x.split('_')) for x in mylist])""",
'jdehesa': """sum((s.split("_") for s in mylist), [])""",
'mogga': """[i for sublist in [j.split('_') for j in mylist] for i in sublist]""",
'Ajax1234': """list(chain(*[[i] if "_" not in i else i.split("_") for i in mylist]))"""
}
print('-----------------------------------------')
for author, method in methods.items():
print('{} time: {}'.format(author, round(timeit(setup=setup, stmt=method), 4)))
print('-----------------------------------------')
Each method is tested against the sample list given in the question about one million times. To keep things readable, each timing result was rounded to four decimal places.
Note: If you have a new, unique method that has not been posted here yet, contact me in the comments and I'll try to add a timing for it too.
Another trick is first to join the list with underscores and then re-split it:
"_".join(mylist).split('_')
You can do:
mylist = ['dog', 'cat', 'mouse_bear', 'lion_tiger_rabbit', 'ant']
result = sum((s.split("_") for s in mylist), [])
print(result)
>>> ['dog', 'cat', 'mouse', 'bear', 'lion', 'tiger', 'rabbit', 'ant']
This works:
[i for sublist in [j.split('_') for j in mylist] for i in sublist]
using the itertools recipe to flatten a list you could do this:
from itertools import chain
mylist = ['dog', 'cat', 'mouse_bear', 'lion_tiger_rabbit', 'ant']
new_list = list(chain.from_iterable(item.split('_') for item in mylist))
print(new_list)
# ['dog', 'cat', 'mouse', 'bear', 'lion', 'tiger', 'rabbit', 'ant']
...or does the import statement violate your one-liner requirement?
Just use 2 for
clauses in your comprehension, e.g.:
>>> mylist = ['dog', 'cat', 'mouse_bear', 'lion_tiger_rabbit', 'ant']
>>> [animal for word in mylist for animal in word.split('_')]
['dog', 'cat', 'mouse', 'bear', 'lion', 'tiger', 'rabbit', 'ant']