Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inserting period after every 3 chars in a string

I have this:

from __future__ import print_function

def f_comma(p_string):
   v_string = p_string
   if (type(v_string) == type(int()) or type(v_string) == type(long()) or  
       type(v_string) == type(float())):
      v_string = str(v_string)
   else:   
      l_string = list(v_string)
      for v_index in range(3, len(l_string), 4):
         l_string.insert(v_index, ',')
      v_result = ''.join(l_string)
   return (v_result)

print (f_comma('qwertyuiopaq'))

It seems that i can't figure it out why if i use a string longer than 11 chars the period stops inserting, but with only 11 chars it works fine. What i'm doing wrong in this piece?

like image 671
udarH3 Avatar asked Jun 18 '15 15:06

udarH3


3 Answers

You can insert a comma after every nth character like this:

>>> my_str = 'qwertyuiopaq'
>>> ','.join(my_str[i:i+3] for i in range(0, len(my_str), 3))
'qwe,rty,uio,paq'

This should work for any arbitrary length of strings too.

Edit: Written as a function in a similar style to @mhawke's answer, with an option to change the grouping/characters.

>>> def f_comma(my_str, group=3, char=','):
...     my_str = str(my_str)
...     return char.join(my_str[i:i+group] for i in range(0, len(my_str), group))
... 
>>> f_comma('qwertyuiopaq')
'qwe,rty,uio,paq'
>>> f_comma('qwertyuiopaq', group=2)
'qw,er,ty,ui,op,aq'
>>> f_comma('qwertyuiopaq', group=2, char='.')
'qw.er.ty.ui.op.aq'
like image 58
Nitzle Avatar answered Oct 12 '22 05:10

Nitzle


Here is an alternative way to do it using slicing:

def f_comma(p_string, n=3):
    return ','.join(p_string[i:i+n] for i in range(0, len(p_string), n))

I don't think that the type checking in your version is necessary. Your code checks for instances of an int, long or float and then converts any of these to a string. You can just convert to a string without checking the type:

def f_comma(p_string, n=3):
    p_string = str(p_string)
    return ','.join(p_string[i:i+n] for i in range(0, len(p_string), n))

>>> f_comma('abcdefghijklmnop')
'abc,def,ghi,jkl,mno,p'
>>> f_comma(1234567890)
'123,456,789,0'
>>> import math
>>> f_comma(math.pi)
'3.1,415,926,535,9'

Now this won't handle all unicode strings:

>>> f_comma(u'abcdefg\u3030\u3031\u3032\u3033')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f_comma
UnicodeEncodeError: 'ascii' codec can't encode characters in position 7-10: ordinal not in range(128)

Here you can use isinstance() (preferable to type() ==) to aid conversion of non-string types:

def f_comma(p_string, n=3):
    if not isinstance(p_string, basestring):    # str or unicode
        p_string = str(p_string)                # convert only non-strings
    return ','.join(p_string[i:i+n] for i in range(0, len(p_string), n))

>>> f_comma(u'abcdefg\u3030\u3031\u3032\u3033')    # returns unicode
u'abc,def,g\u3030\u3031,\u3032\u3033'
>>> f_comma('wowwowwowwow')                        # returns str
'wow,wow,wow,wow'
>>> f_comma(math.pi)                               # returns str
'3.1,415,926,535,9'

Also notice the use of a default argument to specify the segment length:

>>> f_comma('abcdefghijklmnop')
u'abc,def,ghi,jkl,mno,p'
>>> f_comma('abcdefghijklmnop', 6)
u'abcdef,ghijkl,mnop'
like image 23
mhawke Avatar answered Oct 12 '22 04:10

mhawke


Here's why it doesn't work. (Rather than solving your method which is a pretty inefficient one, as others have shown.)

When you .insert() something into your list, every element gets shifted forward a position to make room.

The indexes you calculated earlier with range(3, len(l_string), 4) are then no longer what you want them to be.

like image 1
LondonRob Avatar answered Oct 12 '22 03:10

LondonRob