12

I have a list (array) with mixed

a = ["x", "2", "y"]
b = ["x", 2, "y"]
print ":".join(a)
print ":".join(b)

The first join works, but the second one throws a TypeError exception

I came up with this, but is this the Python solution?

print ":".join(map(str, b))

BTW in the end I just would like to write this string to a file, so if there is a specific solution for that, I'd appreciate that too.

9
  • 4
    Yes, this is probably the most Pythonic way to do it. Commented Dec 19, 2012 at 14:15
  • Either what you have if you prefer brevity, or a try/except loop to normalize all the inputs before joining them if you (arguably) prefer clarity. Commented Dec 19, 2012 at 14:15
  • Looks quite pythonic to me! Commented Dec 19, 2012 at 14:15
  • 1
    One note on terminology -- What you have is a list, not an array. When people say "array" they're usually referring to a numpy.ndarray, but there's also a built-in array module which supplies an array type (which can only hold homogeneous data) Commented Dec 19, 2012 at 14:47
  • 1
    @mgilson In my experience, when people say “array”, they usually mean the language agnostic data structure that an array in most languages is. Commented Dec 19, 2012 at 16:28

1 Answer 1

12

Your solution works nicely and is probably one of the fastest ways to do this for small to medium sized lists, but it creates an unnecessary list (in python2.x). Usually that's not a problem, but in a few cases, depending on the object b, it could be an issue. Another which is lazy in python2 as well as python 3 is:

':'.join(str(x) for x in b)

Some timings for python 2.7.3:

$ python -m timeit -s 'b = ["x", 2, "y"]' '":".join(map(str,b))'
1000000 loops, best of 3: 1.66 usec per loop
$python -m timeit -s 'b = ["x", 2, "y"]' '":".join([str(x) for x in b])'
1000000 loops, best of 3: 1.49 usec per loop
$ python -m timeit -s 'b = ["x", 2, "y"]' '":".join(str(x) for x in b)'
100000 loops, best of 3: 3.26 usec per loop
$python -m timeit -s 'from itertools import imap; b = ["x", 2, "y"]' '":".join(imap(str,b))'
100000 loops, best of 3: 2.83 usec per loop

Some timings for python3.2:

$ python3 -m timeit -s 'b = ["x", 2, "y"]' '":".join(map(str,b))'
100000 loops, best of 3: 2.6 usec per loop
$ python3 -m timeit -s 'b = ["x", 2, "y"]' '":".join([str(x) for x in b])'
100000 loops, best of 3: 2.08 usec per loop
$ python3 -m timeit -s 'b = ["x", 2, "y"]' '":".join(str(x) for x in b)'
100000 loops, best of 3: 3.39 usec per loop

Note that if you let the loop get a lot bigger, the differences become less important:

python2.7.3:

$ python -m timeit -s 'b = list(range(10000))' '":".join(str(x) for x in b)'
100 loops, best of 3: 4.83 msec per loop
$ python -m timeit -s 'b = list(range(10000))' '":".join([str(x) for x in b])'
100 loops, best of 3: 4.33 msec per loop
$ python -m timeit -s 'b = list(range(10000))' '":".join(map(str,b))'
100 loops, best of 3: 3.29 msec per loop

python 3.2.0

$ python3 -m timeit -s 'b = list(range(10000))' '":".join(str(x) for x in b)'
100 loops, best of 3: 6.42 msec per loop
$ python3 -m timeit -s 'b = list(range(10000))' '":".join([str(x) for x in b])'
100 loops, best of 3: 5.51 msec per loop
$ python3 -m timeit -s 'b = list(range(10000))' '":".join(map(str,b))'
100 loops, best of 3: 4.55 msec per loop

*all timings done on my MacbookPro, OS-X 10.5.8 intel core2duo ....

Notes,

  • python2.x is faster than python3.x in all cases (for me)
  • List-comprehension turns out to be fastest for your example list, but map is faster for a larger list. map is probably slower for the small list as you need to look up the function whereas the list comprehension cannot be "shadowed", so no lookup needs to be performed. There may be another turn-around point for HUGE lists where the time it takes to build the intermediate list becomes significant.
  • generator expression is always the slowest (but lazy in both cases)
Sign up to request clarification or add additional context in comments.

4 Comments

if you import itertools.imap you can get the same performance gain: ':'.join(imap(str, b))
@David -- imap does better than the generator, but still much worse than map for this small example (and it's only available in python2.x). Thanks for the suggestion though. I've added it to the timings.
I'm happy to improve this answer if you leave a suggestion :-)
itertools.imap is only available in python2 because in python 3 map is itertools.imap, to get the old one back, you would need list(map(...))

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.