3

I would like to add brackets to each character in a string. So

"HelloWorld"

should become:

"[H][e][l][l][o][W][o][r][l][d]"

I have used this code:

word = "HelloWorld"
newWord = ""
for letter in word:
    newWord += "[%s]" % letter

which is the most straightforward way to do it but the string concatenations are pretty slow. Any suggestions on speeding up this code.

Mehdi Nellen
  • 8,486
  • 4
  • 33
  • 48

3 Answers3

6
>>> s = "HelloWorld"
>>> ''.join('[{}]'.format(x) for x in s)
'[H][e][l][l][o][W][o][r][l][d]'

If string is huge then using str.join with a list comprehension will be faster and memory efficient than using a generator expression(https://stackoverflow.com/a/9061024/846892):

>>> ''.join(['[{}]'.format(x) for x in s])
'[H][e][l][l][o][W][o][r][l][d]'

From Python performance tips:

Avoid this:

s = ""
for substring in list:
    s += substring

Use s = "".join(list) instead. The former is a very common and catastrophic mistake when building large strings.

Community
  • 1
  • 1
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

The most pythonic way would probably be with a generator comprehension:

>>> s = "HelloWorld"
>>> "".join("[%s]" % c for c in s)
'[H][e][l][l][o][W][o][r][l][d]'

Ashwini Chaudhary's answer is very similar, but uses the modern (Python3) string format function. The old string interpolation with % still works fine and is a bit simpler.

A bit more creatively, inserting ][ between each character, and surrounding it all with []. I guess this might be a bit faster, since it doesn't do as many string interpolations, but speed shouldn't be an issue here.

>>> "[" + "][".join(s) + "]"
'[H][e][l][l][o][W][o][r][l][d]'
jdm
  • 9,470
  • 12
  • 58
  • 110
  • looks great, I've used this code, although haven't checked whether it is the fastest one. :) – Mehdi Nellen Feb 04 '14 at 14:22
  • @MehdiNellen: Without knowing more about your code, I guess the difference in speed shouldn't matter much. Go for the cleanest version, or the one you understand best. If it turns out to be a bottleneck, you can still optimize afterwards. – jdm Feb 04 '14 at 14:23
  • >>> timeit.timeit("''.join('[%s]' % c for c in 'lol')", number=100000) 0.36499309539794922 >>> timeit.timeit('"[" + "][".join("lol") + "]"', number=100000) 0.1732938289642334 – Mehdi Nellen Feb 04 '14 at 14:28
  • Your second option is the first one I thought of, except I would use format: `"[{}]".format(']['.join(s))` – Duncan Feb 04 '14 at 14:32
  • FWIW, if you want to save a few microseconds, `python timeit.py` on my system says `"".join("[%s]" % c for c in s)` is 4.7μs, `"["+"][".join(s)+"]"` is 1.41μs per loop (and my alternative using format is 1.8μs). YMMV – Duncan Feb 04 '14 at 14:38
1

If you are concerned about speed and need a fast implementation, try to determine an implementation which offloads the iteration to the underline native module. This is true for at least in CPython.

Suggested Implementation

"[{}]".format(']['.join(s))

Output

'[H][e][l][l][o][W][o][r][l][d]'

Comparing with a competing solution

In [12]: s = "a" * 10000

In [13]: %timeit "[{}]".format(']['.join(s))
1000 loops, best of 3: 215 us per loop

In [14]: %timeit ''.join(['[{}]'.format(x) for x in s])
100 loops, best of 3: 3.06 ms per loop

In [15]: %timeit ''.join('[{}]'.format(x) for x in s)
100 loops, best of 3: 3.26 ms per loop
Abhijit
  • 62,056
  • 18
  • 131
  • 204