47

I am trying to map the str.split function to an array of string. namely, I would like to split all the strings in a string array that follow the same format. Any idea how to do that with map in python? For example let's assume we have a list like this:

a = ['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']

want to split the strings by space ( split(" ")) using map to have a list as:

[['2011-12-22', '46:31:11'], ['2011-12-20', '20:19:17'], ['2011-12-20', '01:09:21']]

5 Answers 5

63

Though it isn't well known, there is a function designed just for this purpose, operator.methodcaller:

>>> from operator import methodcaller
>>> a = ['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']
>>> list(map(methodcaller("split", " "), a))
[['2011-12-22', '46:31:11'], ['2011-12-20', '20:19:17'], ['2011-12-20', '01:09:21']]

This technique is faster than equivalent approaches using lambda expressions.

Sign up to request clarification or add additional context in comments.

1 Comment

This is the absolutely best answer, because it allows me to pass the str.split keyword argument sep=" " to the str.split function. I'm not sure how that could be accomplished otherwise, because map(str.split('\t'), a) does not work. Thanks!
44
map(lambda x: x.split(), a) 

but, using a list comprehension

[x.split() for x in a] 

is much clearer in this case.

2 Comments

Even though the OP asks explicitly for map, this answer shows that it's cleaner and more Pythonic to use a list comprehension.
@kojiro That is very subjective. Coming from a Functional Programming background, the map is much easier to read/cleaner than a list comprehension (to me).
10

This is how I do it:

>>> a=['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']
>>> map(str.split, a)
[['2011-12-22', '46:31:11'], ['2011-12-20', '20:19:17'], ['2011-12-20', '01:09:21']]

This only works when you know you have a list of str (i.e. not just a list of things that implement the split method in a way compatible with str). It also relies on using the default behaviour of split(), which splits on any whitespace, rather than using x.split(' '), which splits on space characters only (i.e. not tabs, newlines, or other whitespace), because you can't pass another argument using this method. For calling behaviour more complex than this, I would use a list comprehension.

2 Comments

How to give arguments to split like "\t" and "1" like that
@Vignesh "For calling behaviour more complex than this, I would use a list comprehension". The thing you're mapping over the list has to be callable with one argument. You can always wrap the split method call in a new function (possibly defined inline using lambda), in order to make something that can be called with one argument and which will also pass the additional separator argument. But that usually ends up less readable than [x.split('\t') for x in a], unless it's something you would have defined and named anyway.
9

Use map in conjunction with a function. A neat way is to use a lambda function:

>>> a=['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']
>>> map(lambda s: s.split(), a)
[['2011-12-22', '46:31:11'], ['2011-12-20', '20:19:17'],
 ['2011-12-20', '01:09:21']]

1 Comment

you could simplify with map(str.split, a)
2

Community wiki answer to compare other answers given

>>> from timeit import Timer
>>> t = {}
>>> t['methodcaller'] = Timer("map(methodcaller('split', ' '), a)", "from operator import methodcaller; a=['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']")
>>> t['lambda'] = Timer("map(lambda s: s.split(), a)", "a = ['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']")
>>> t['listcomp'] = Timer("[s.split() for s in a]", "a = ['2011-12-22 46:31:11','2011-12-20 20:19:17', '2011-12-20 01:09:21']")
>>> for name, timer in t.items():
...     print '%s: %.2f usec/pass' % (name, 1000000 * timer.timeit(number=100000)/100000)
... 
listcomp: 2.08 usec/pass
methodcaller: 2.87 usec/pass
lambda: 3.10 usec/pass

1 Comment

Amusing how they ended up in order according to speed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.