Inserting colon in a string

11 views
Skip to first unread message

vipul borikar

unread,
Apr 30, 2013, 9:52:16 AM4/30/13
to pytho...@googlegroups.com
Hi list,
          I want to convert a hex string in colon separated string like this:

str1 = 0x21000024ff3afd2b   output = 21:00:00:24:ff:3a:fd:2b

I tried something like this:

###########################
output = output[2:]
               
li = list(output)
               
count = 2

while count < len(li):
   
         li.insert(count, ':')
   
         count += 3
   
print "".join(li)
################################

The above code looks little messy.

Anybody has any better idea to do it?

--
Thanks 

Vipul Borikar
"Our task must be to free ourselves...by widening our circle of compassion to embrace all living creatures and the whole of nature and its beauty."

Dhananjay Nene

unread,
Apr 30, 2013, 10:02:19 AM4/30/13
to PythonPune
input = "0x21000024ff3afd2b"
assert(":".join(input[i:i+2] for i in range(2, len(input), 2)) == "21:00:00:24:ff:3a:fd:2b")


--
You received this message because you are subscribed to the Google Groups "Python Pune" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pythonpune+...@googlegroups.com.
To post to this group, send email to pytho...@googlegroups.com.
Visit this group at http://groups.google.com/group/pythonpune?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
----------------------------------------------------------------------------------------------------------------------------------
http://blog.dhananjaynene.com twitter: @dnene google plus: http://gplus.to/dhananjaynene

Dhananjay Nene

unread,
Apr 30, 2013, 11:05:49 AM4/30/13
to PythonPune
If you wanted to be particularly picky about performance (not required in most cases)

def pairs(s):
    try :
        i = iter(s)
        while True :
            c1 = next(i)
            c2 = next(i) 
            yield c1 + c2
    except StopIteration :
        pass
    

assert(":".join(pairs("0x21000024ff3afd2b"[2:])) == "21:00:00:24:ff:3a:fd:2b")    

Anand Chitipothu

unread,
Apr 30, 2013, 12:12:44 PM4/30/13
to PythonPune
On Tue, Apr 30, 2013 at 8:35 PM, Dhananjay Nene <dhananj...@gmail.com> wrote:
If you wanted to be particularly picky about performance (not required in most cases)

def pairs(s):
    try :
        i = iter(s)
        while True :
            c1 = next(i)
            c2 = next(i) 
            yield c1 + c2
    except StopIteration :
        pass
    

assert(":".join(pairs("0x21000024ff3afd2b"[2:])) == "21:00:00:24:ff:3a:fd:2b")    

I don't think this will be any faster than the earlier implementation.

Just for fun, here is another approach.

def pairs(s):
    return (a+b for a, b in zip(s[::2], s[1::2]))

assert(":".join(pairs("0x21000024ff3afd2b"[2:])) == "21:00:00:24:ff:3a:fd:2b")    

Anand

steve

unread,
Apr 30, 2013, 12:27:04 PM4/30/13
to pytho...@googlegroups.com, Anand Chitipothu
Hi,
On Tuesday 30 April 2013 09:42 PM, Anand Chitipothu wrote:
>
> On Tue, Apr 30, 2013 at 8:35 PM, Dhananjay Nene <dhananj...@gmail.com
> <mailto:dhananj...@gmail.com>> wrote:
>
> If you wanted to be particularly picky about performance (not required in
> most cases)
>
> def pairs(s):
> try :
> i = iter(s)
> while True :
> c1 = next(i)
> c2 = next(i)
> yield c1 + c2
> except StopIteration :
> pass
>
> assert(":".join(pairs("0x21000024ff3afd2b"[2:])) == "21:00:00:24:ff:3a:fd:2b")
>
>
> I don't think this will be any faster than the earlier implementation.
>

Actually, it is significantly faster:

>>> def pairs(s):
... try :
... i = iter(s)
... while True :
... c1 = next(i)
... c2 = next(i)
... yield c1 + c2
... except StopIteration :
... pass
...
>>> timeit.timeit('pairs("0x21000024ff3afd2b")', setup='from __main__ import
pairs')
0.7603280544281006
>>> timeit.timeit('":".join(s[i:i+2] for i in range(2, len(s), 2))',
setup='s="0x21000024ff3afd2b"')
4.8088250160217285
>>> timeit.timeit("':'.join( a+b for a, b in zip(s[::2], s[1::2]) )",
setup='s="0x21000024ff3afd2b"')
6.071056127548218
>>>

cheers,
- steve

steve

unread,
Apr 30, 2013, 12:34:36 PM4/30/13
to pytho...@googlegroups.com
On second thoughts ...
^^^^^^^^^^^^ this just creates the generator object ...my bad, so the revised
test is:

> 0.7603280544281006
> >>> timeit.timeit('":".join(s[i:i+2] for i in range(2, len(s), 2))',
> setup='s="0x21000024ff3afd2b"')
> 4.8088250160217285
> >>> timeit.timeit("':'.join( a+b for a, b in zip(s[::2], s[1::2]) )",
> setup='s="0x21000024ff3afd2b"')
> 6.071056127548218
> >>>
>

>>> timeit.timeit('":".join(pairs("0x21000024ff3afd2b"[2:]))', setup='from
__main__ import pairs')
9.683159828186035

...which is actually worse. hmm, interesting.

cheers,
- steve

Dhananjay Nene

unread,
Apr 30, 2013, 12:53:11 PM4/30/13
to PythonPune
Thanks steve for setting up an interesting observation. 
Yes, it is peculiar. I defined another function pair2 (which had a minor change compared to pair) 

def pairs2(s):
    try :
        i = iter(s)
        while True :
            yield next(i) + next(i)
    except StopIteration :
        pass

I was just trying to avoid creation of two temporary variables here.

On Python 2.7.3 I got

>>> timeit.timeit('":".join(pairs("0x21000024ff3afd2b"))', setup='from __main__ import pairs')
4.479202032089233
>>> timeit.timeit('":".join(pairs2("0x21000024ff3afd2b"))', setup='from __main__ import pairs2')
4.3042449951171875
>>> timeit.timeit('":".join(s[i:i+2] for i in range(2, len(s), 2))', setup='s="0x21000024ff3afd2b"')
1.9831359386444092
>>> timeit.timeit("':'.join( a+b for a, b in zip(s[::2], s[1::2]) )", setup='s="0x21000024ff3afd2b"')
2.999051809310913


On Python 3.3.0, the results I got were :

>>> timeit.timeit('":".join(pairs("0x21000024ff3afd2b"))', setup='from __main__ import pairs')
4.570932610997261
>>> timeit.timeit('":".join(pairs2("0x21000024ff3afd2b"))', setup='from __main__ import pairs2')
4.241085749999911
>>> timeit.timeit('":".join(s[i:i+2] for i in range(2, len(s), 2))', setup='s="0x21000024ff3afd2b"')
3.5848920159987756
>>> timeit.timeit("':'.join( a+b for a, b in zip(s[::2], s[1::2]) )", setup='s="0x21000024ff3afd2b"')
3.166921207000996

Whereas on PyPy 1.9 (Python 2.7.2) I got

>>>> timeit.timeit('":".join(pairs("0x21000024ff3afd2b"))', setup='from __main__ import pairs')
0.845271110534668
>>>> timeit.timeit('":".join(pairs2("0x21000024ff3afd2b"))', setup='from __main__ import pairs2')
0.7255899906158447
>>>> timeit.timeit('":".join(s[i:i+2] for i in range(2, len(s), 2))', setup='s="0x21000024ff3afd2b"')
0.626521110534668
>>>> timeit.timeit("':'.join( a+b for a, b in zip(s[::2], s[1::2]) )", setup='s="0x21000024ff3afd2b"')
2.3363211154937744

Go figure it out for what it is worth :)

steve

unread,
Apr 30, 2013, 1:10:02 PM4/30/13
to pytho...@googlegroups.com, Dhananjay Nene
Hi Dhananjay,

On Tuesday 30 April 2013 10:23 PM, Dhananjay Nene wrote:
>
> ....[snip]...
> Thanks steve for setting up an interesting observation.
> Yes, it is peculiar. I defined another function pair2 (which had a minor change
> compared to pair)
>
> def pairs2(s):
> try :
> i = iter(s)
> while True :
> yield next(i) + next(i)
> except StopIteration :
> pass
>
> I was just trying to avoid creation of two temporary variables here.
>
> On Python 2.7.3 I got
>
> >>> timeit.timeit('":".join(pairs("0x21000024ff3afd2b"))', setup='from __main__
> import pairs')
> 4.479202032089233
> >>> timeit.timeit('":".join(pairs2("0x21000024ff3afd2b"))', setup='from
> __main__ import pairs2')
> 4.3042449951171875
> >>> timeit.timeit('":".join(s[i:i+2] for i in range(2, len(s), 2))',
> setup='s="0x21000024ff3afd2b"')
> 1.9831359386444092
> >>> timeit.timeit("':'.join( a+b for a, b in zip(s[::2], s[1::2]) )",
> setup='s="0x21000024ff3afd2b"')
> 2.999051809310913
>
>

I have a feeling this has something to do with the function call overhead, because:

>>> timeit.timeit('":".join(pairs("0x21000024ff3afd2b"[2:]))', setup='from
__main__ import pairs')
9.249284982681274
>>> timeit.timeit('":".join(pairs2("0x21000024ff3afd2b"[2:]))', setup='from
__main__ import pairs2')
9.641417026519775
>>> timeit.timeit("':'.join( next(i) + next(i) for _ in s[2:] )",
setup="s='0x21000024ff3afd2b'; i = iter(s[2:])")
2.451604127883911
>>>

cheers,
- steve

Dhananjay Nene

unread,
Apr 30, 2013, 1:11:43 PM4/30/13
to steve, PythonPune
I have a feeling you just nailed it :)

steve

unread,
Apr 30, 2013, 1:20:56 PM4/30/13
to pytho...@googlegroups.com
Hi,

Although unrelated to the OP's question, what bothers me is this tho' ...
On Tuesday 30 April 2013 10:41 PM, Dhananjay Nene wrote:
> [ ...snip ...]
>
>
> On Tue, Apr 30, 2013 at 10:40 PM, steve <st...@lonetwin.net
> <mailto:st...@lonetwin.net>> wrote:
> >>> timeit.timeit("':'.join( next(i) + next(i) for _ in s[2:] )",
> setup="s='0x21000024ff3afd2b'; i = iter(s[2:])")
> 2.451604127883911
> >>>
>
>
> I have a feeling you just nailed it :)
>

>>> s = "0x21000024ff3afd2b"
>>> i = iter(s)
>>> for x in range(10000):
... next(i)
...
'0'
'x'
'2'
'1'
'0'
'0'
'0'
'0'
'2'
'4'
'f'
'f'
'3'
'a'
'f'
'd'
'2'
'b'
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
StopIteration
>>> ''.join(next(i) for _ in range(10000))
'0x21000024ff3afd2b'

Is that (not raising a StopIteration) valid (ie: defined) behaviour ?

cheers,
- steve

Dhananjay Nene

unread,
Apr 30, 2013, 1:24:01 PM4/30/13
to steve, PythonPune
We have a clear winner at least from a perf perspecive

s='0x21000024ff3afd2b'; i = iter(s[2:])
':'.join( next(i) + next(i) for _ in s[2:] )

Beats all the other options quite handsomely across 2.7.2, 3.3.0 and pypy 1.9 (python 2.7.2)

steve

unread,
Apr 30, 2013, 1:24:27 PM4/30/13
to pytho...@googlegroups.com
sorry I didn't copy past the obvious:
>>> i = iter(s)

between the two

vipul borikar

unread,
May 2, 2013, 1:22:24 AM5/2/13
to pytho...@googlegroups.com
Thanks everyone for the interesting replies...


--
You received this message because you are subscribed to the Google Groups "Python Pune" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pythonpune+unsubscribe@googlegroups.com.

To post to this group, send email to pytho...@googlegroups.com.
Visit this group at http://groups.google.com/group/pythonpune?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply all
Reply to author
Forward
0 new messages