From: Peter Otten on
python(a)bdurham.com wrote:

> Does Python provide a way to format a string according to a
> 'picture' format?
>
> For example, if I have a string '123456789' and want it formatted
> like '(123)-45-(678)[9]', is there a module or function that will
> allow me to do this or do I need to code this type of
> transformation myself?

A basic implementation without regular expressions:

>>> def picture(s, pic, placeholder="@"):
.... parts = pic.split(placeholder)
.... result = [None]*(len(parts)+len(s))
.... result[::2] = parts
.... result[1::2] = s
.... return "".join(result)
....
>>>
>>> picture("123456789", "(@@@)-@@-(@@@)[@]")
'(123)-45-(678)[9]'

Peter
From: Olof Bjarnason on
2010/2/10 Peter Otten <__peter__(a)web.de>:
> python(a)bdurham.com wrote:
>
>> Does Python provide a way to format a string according to a
>> 'picture' format?
>>
>> For example, if I have a string '123456789' and want it formatted
>> like '(123)-45-(678)[9]', is there a module or function that will
>> allow me to do this or do I need to code this type of
>> transformation myself?
>
> A basic implementation without regular expressions:
>
>>>> def picture(s, pic, placeholder="@"):
> ...     parts = pic.split(placeholder)
> ...     result = [None]*(len(parts)+len(s))
> ...     result[::2] = parts
> ...     result[1::2] = s
> ...     return "".join(result)
> ...
>>>>
>>>> picture("123456789", "(@@@)-@@-(@@@)[@]")
> '(123)-45-(678)[9]'
>
> Peter
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Inspired by your answer here's another version:

>>> def picture(s, pic):
.... if len(s)==0: return pic
.... if pic[0]=='#': return s[0]+picture(s[1:], pic[1:])
.... return pic[0]+picture(s, pic[1:])
....
>>> picture("123456789", "(###)-##-(###)[#]")
'(123)-45-(678)[9]'
>>>

--
http://olofb.wordpress.com
From: Alf P. Steinbach on
* Olof Bjarnason:
> 2010/2/10 Peter Otten <__peter__(a)web.de>:
>> python(a)bdurham.com wrote:
>>
>>> Does Python provide a way to format a string according to a
>>> 'picture' format?
>>>
>>> For example, if I have a string '123456789' and want it formatted
>>> like '(123)-45-(678)[9]', is there a module or function that will
>>> allow me to do this or do I need to code this type of
>>> transformation myself?
>> A basic implementation without regular expressions:
>>
>>>>> def picture(s, pic, placeholder="@"):
>> ... parts = pic.split(placeholder)
>> ... result = [None]*(len(parts)+len(s))
>> ... result[::2] = parts
>> ... result[1::2] = s
>> ... return "".join(result)
>> ...
>>>>> picture("123456789", "(@@@)-@@-(@@@)[@]")
>> '(123)-45-(678)[9]'
>>
>> Peter
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> Inspired by your answer here's another version:
>
>>>> def picture(s, pic):
> ... if len(s)==0: return pic
> ... if pic[0]=='#': return s[0]+picture(s[1:], pic[1:])
> ... return pic[0]+picture(s, pic[1:])
> ...
>>>> picture("123456789", "(###)-##-(###)[#]")
> '(123)-45-(678)[9]'

I learned a bit by Peter Otten's example; I would have gotten to that notation
sooner or later, but that example made it 'sooner' :-).

I think your version is cute.

I'd probably write it in a non-recursive way, though, like

def picture( s, pic, placeholder = "@" ):
result = ""
char_iter = iter( s )
for c in pic:
result += c if c != placeholder else next( char_iter )
return result

Of course this is mostly personal preference, but there is also a functional
difference.

With your version an IndexError will be raised if there are too /many/
characters in s, while too few characters in s will yield "#" in the result.

With my version a StopIteration will be raised if there are to /few/ characters
in s, while too many characters will just have the extraneous chars ignored.


Cheers,

- Alf
From: Olof Bjarnason on
2010/2/10 Alf P. Steinbach <alfps(a)start.no>:
> * Olof Bjarnason:
>>
>> 2010/2/10 Peter Otten <__peter__(a)web.de>:
>>>
>>> python(a)bdurham.com wrote:
>>>
>>>> Does Python provide a way to format a string according to a
>>>> 'picture' format?
>>>>
>>>> For example, if I have a string '123456789' and want it formatted
>>>> like '(123)-45-(678)[9]', is there a module or function that will
>>>> allow me to do this or do I need to code this type of
>>>> transformation myself?
>>>
>>> A basic implementation without regular expressions:
>>>
>>>>>> def picture(s, pic, placeholder="@"):
>>>
>>> ...     parts = pic.split(placeholder)
>>> ...     result = [None]*(len(parts)+len(s))
>>> ...     result[::2] = parts
>>> ...     result[1::2] = s
>>> ...     return "".join(result)
>>> ...
>>>>>>
>>>>>> picture("123456789", "(@@@)-@@-(@@@)[@]")
>>>
>>> '(123)-45-(678)[9]'
>>>
>>> Peter
>>> --
>>> http://mail.python.org/mailman/listinfo/python-list
>>>
>>
>> Inspired by your answer here's another version:
>>
>>>>> def picture(s, pic):
>>
>> ...   if len(s)==0: return pic
>> ...   if pic[0]=='#': return s[0]+picture(s[1:], pic[1:])
>> ...   return pic[0]+picture(s, pic[1:])
>> ...
>>>>>
>>>>> picture("123456789", "(###)-##-(###)[#]")
>>
>> '(123)-45-(678)[9]'
>
> I learned a bit by Peter Otten's example; I would have gotten to that
> notation sooner or later, but that example made it 'sooner' :-).
>
> I think your version is cute.

Thanks!

Here's another version (maybe a little more readable?):

def first(s): return s[0]

def rest(s): return s[1:]

def picture(s, pic):
if not s: return pic
if first(pic)=='#': return first(s)+picture(rest(s), rest(pic))
return first(pic)+picture(s, rest(pic))


>
> I'd probably write it in a non-recursive way, though, like
>
>    def picture( s, pic, placeholder = "@" ):
>        result = ""
>        char_iter = iter( s )
>        for c in pic:
>            result += c if c != placeholder else next( char_iter )
>        return result
>
> Of course this is mostly personal preference, but there is also a functional
> difference.
>
> With your version an IndexError will be raised if there are too /many/
> characters in s, while too few characters in s will yield "#" in the result.
>
> With my version a StopIteration will be raised if there are to /few/
> characters in s, while too many characters will just have the extraneous
> chars ignored.
>
>
> Cheers,
>
> - Alf
> --
> http://mail.python.org/mailman/listinfo/python-list
>



--
http://olofb.wordpress.com
From: MRAB on
Olof Bjarnason wrote:
> 2010/2/10 Peter Otten <__peter__(a)web.de>:
>> python(a)bdurham.com wrote:
>>
>>> Does Python provide a way to format a string according to a
>>> 'picture' format?
>>>
>>> For example, if I have a string '123456789' and want it formatted
>>> like '(123)-45-(678)[9]', is there a module or function that will
>>> allow me to do this or do I need to code this type of
>>> transformation myself?
>> A basic implementation without regular expressions:
>>
>>>>> def picture(s, pic, placeholder="@"):
>> ... parts = pic.split(placeholder)
>> ... result = [None]*(len(parts)+len(s))
>> ... result[::2] = parts
>> ... result[1::2] = s
>> ... return "".join(result)
>> ...
>>>>> picture("123456789", "(@@@)-@@-(@@@)[@]")
>> '(123)-45-(678)[9]'
>>
>> Peter
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> Inspired by your answer here's another version:
>
>>>> def picture(s, pic):
> ... if len(s)==0: return pic
> ... if pic[0]=='#': return s[0]+picture(s[1:], pic[1:])
> ... return pic[0]+picture(s, pic[1:])
> ...
>>>> picture("123456789", "(###)-##-(###)[#]")
> '(123)-45-(678)[9]'
>
Here's a version without recursion:

>>> def picture(s, pic):
.... pic = pic.replace("%", "%%").replace("#", "%s")
.... return pic % tuple(s)
....
>>> picture("123456789", "(###)-##-(###)[#]")
'(123)-45-(678)[9]'