10

I am trying to convert 10000000C9ABCDEF to 10:00:00:00:c9:ab:cd:ef

This is needed because 10000000C9ABCDEF format is how I see HBAs or host bust adapaters when I login to my storage arrays. But the SAN Switches understand 10:00:00:00:c9:ab:cd:ef notation.

I have only been able to accomplish till the following:

#script to convert WWNs to lowercase and add the :.
def wwn_convert():
    while True:
        wwn = (input('Enter the WWN or q to quit- '))
        list_wwn = list(wwn)
        list_wwn = [x.lower() for x in list_wwn]
        lower_wwn = ''.join(list_wwn)
        print(lower_wwn)
    if wwn == 'q':
        break

wwn_convert()

I tried ':'.join, but that inserts : after each character, so I get 1:0:0:0:0:0:0:0:c:9:a:b:c:d:e:f

I want the .join to go through a loop where I can say something like for i in range (0, 15, 2) so that it inserts the : after two characters, but not quite sure how to go about it. (Good that Python offers me to loop in steps of 2 or any number that I want.)

Additionally, I will be thankful if someone could direct me to pointers where I could script this better...

Please help.

I am using Python Version 3.2.2 on Windows 7 (64 Bit)

César
  • 9,939
  • 6
  • 53
  • 74

6 Answers6

6

Here is another option:

>>> s = '10000000c9abcdef'
>>> ':'.join(a + b for a, b in zip(*[iter(s)]*2))
'10:00:00:00:c9:ab:cd:ef'

Or even more concise:

>>> import re
>>> ':'.join(re.findall('..', s))
'10:00:00:00:c9:ab:cd:ef'
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
2
>>> s = '10000000C9ABCDEF'
>>> ':'.join([s[x:x+2] for x in range(0, len(s)-1, 2)])
'10:00:00:00:C9:AB:CD:EF'

Explanation:

':'.join(...) returns a new string inserting ':' between the parts of the iterable

s[x:x+2] returns a substring of length 2 starting at x from s

range(0, len(s) - 1, 2) returns a list of integers with a step of 2

so the list comprehension would split the string s in substrings of length 2, then the join would put them back together but inserting ':' between them.

Facundo Casco
  • 10,065
  • 8
  • 42
  • 63
1

I think what would help you out the most is a construction in python called a slice. I believe that you can use them on any iterable object, including strings, making them quite useful and something that is generally a very good idea to know how to use.

>>> s = '10000000C9ABCDEF'
>>> [s.lower()[i:i+2] for i in range(0, len(s)-1, 2)]
['10', '00', '00', '00', 'c9', 'ab', 'cd', 'ef']
>>> ':'.join([s.lower()[i:i+2] for i in range(0, len(s)-1, 2)])
'10:00:00:00:c9:ab:cd:ef'

If you'd like to read some more about slices, they're explained very nicely in this question, as well as a part of the actual python documentation.

Community
  • 1
  • 1
Dan Bolan
  • 11
  • 4
  • This is great....You guys are awesome....I think pretty soon I am going to be wondering which solution will be best because there are more than one way to resolve things in Python. Thats awesome....may be time will tell me which is a better method to use for a given problem.... – pritesh_ugrankar Dec 02 '11 at 03:25
  • It's funny that you mention that... One of Python's guiding principles is that "There should be one-- and preferably only one --obvious way to do it." It's part of what's called the Zen of Python, you can read it if you use `import this` in the Python Interpreter. Alternatively you can read it [here.](http://www.python.org/dev/peps/pep-0020/) – Dan Bolan Dec 02 '11 at 18:49
1
>>> s='10000000C9ABCDEF'
>>> si=iter(s)
>>> ':'.join(c.lower()+next(si).lower() for c in si)
>>> '10:00:00:00:c9:ab:cd:ef'

In lambda form:

>>> (lambda x: ':'.join(c.lower()+next(x).lower() for c in x))(iter(s))
'10:00:00:00:c9:ab:cd:ef'
Austin Marshall
  • 2,991
  • 16
  • 14
0

Here is my simple, straightforward solution:

s = '10000000c9abcdef'

new_s = str()
for i in range(0, len(s)-1, 2):
    new_s += s[i:i+2]
    if i+2 < len(s):
        new_s += ':'

>>> new_s
'10:00:00:00:c9:ab:cd:ef'
0

It may be done using grouper recipe from here.

from itertools import izip_longest

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

Using this function, the code will look like:

def join(it):
    for el in it:
        yield ''.join(el)

':'.join(join(grouper(2, s)))

It works this way:

grouper(2,s) returns tuples '1234...' -> ('1','2'), ('3','4') ...

def join(it) does this: ('1','2'), ('3','4') ... -> '12', '34' ...

':'.join(...) creates a string from iterator: '12', '34' ... -> '12:34...'

Also, it may be rewritten as:

':'.join(''.join(el) for el in grouper(2, s))
ovgolovin
  • 13,063
  • 6
  • 47
  • 78
  • @JohnMachin I don't agree. Furthermore, I would add that it's quite simple and straightforward. It uses a standard function `grouper` from the module `itertools`, and what is still left to do is to join the output tuples by `''.join`, and join those joined tuples by `':'.join`. There is not slices prone to off-by-one errors, etc. Simple and straightforward! (Still, the matter of taste I think). – ovgolovin Dec 01 '11 at 21:00
  • For those who are utterly confused with the code like John, try to understand how [this](http://stackoverflow.com/questions/7093121/conjoin-function-made-in-functional-style) recursive geneartor works. If you understand, everything connected with generators will be a bit easier. – ovgolovin Dec 01 '11 at 21:09
  • If you didn't want to wrap this around the `grouper()` function, you could still 1-liner it (where `s` is the input string): `':'.join(''.join(t).lower() for t in itertools.izip_longest(*[iter(s)]* 2))`. – jathanism Dec 01 '11 at 21:30
  • @jathanism But then it means we are reimplementing `grouper` code. This means that if for example we want to group symbols by 3, we would need to understand how it works. With `grouper` it would only require to change the parameter from 2 to 3 without worrying about the correctness of the corrections. This code snippet is very little and easy to grasp, so here it's not a big deal. But still I like to use standard, robust, checked with time solutions. – ovgolovin Dec 01 '11 at 22:03
  • Thank you ovgolovin....however, let me confess that I am still at a stage where I am learning Python in particular and programming in general..I had done some simple C/C++ Programs a few years ago, so am familiar with some of the basic....But the stuff you gave looks like some really advanced Python...wow.... – pritesh_ugrankar Dec 02 '11 at 03:27
  • @scriptq It just the impression that it's difficult. Reading [this](http://docs.python.org/howto/functional.html) article was enough to grasp a lot of thing about functional programming in Python. – ovgolovin Dec 02 '11 at 11:11