MLSC February 2016

Print letters in specific pattern in Python

I have the follwing string and I split it:

>>> st = '%2g%k%3p'
>>> l = filter(None, st.split('%'))
>>> print l
['2g', 'k', '3p']

Now I want to print the g letter two times, the k letter one time and the p letter three times:

ggkppp

How is it possible?

Answers


Anton Protopopov February 2016

You could use generator with isdigit() to check wheter your first symbol is digit or not and then return following string with appropriate count. Then you could use join to get your output:

''.join(i[1:]*int(i[0]) if i[0].isdigit() else i for i in l)

Demonstration:

In [70]: [i[1:]*int(i[0]) if i[0].isdigit() else i for i in l ]
Out[70]: ['gg', 'k', 'ppp']

In [71]: ''.join(i[1:]*int(i[0]) if i[0].isdigit() else i for i in l)
Out[71]: 'ggkppp'

EDIT

Using re module when first number is with several digits:

''.join(re.search('(\d+)(\w+)', i).group(2)*int(re.search('(\d+)(\w+)', i).group(1)) if re.search('(\d+)(\w+)', i) else i for i in l)

Example:

In [144]: l = ['12g', '2kd', 'h', '3p']

In [145]: ''.join(re.search('(\d+)(\w+)', i).group(2)*int(re.search('(\d+)(\w+)', i).group(1)) if re.search('(\d+)(\w+)', i) else i for i in l)
Out[145]: 'ggggggggggggkdkdhppp'

EDIT2

For your input like:

st = '%2g_%3k%3p'

You could replace _ with empty string and then add _ to the end if the work from list endswith the _ symbol:

st = '%2g_%3k%3p'
l = list(filter(None, st.split('%')))
''.join((re.search('(\d+)(\w+)', i).group(2)*int(re.search('(\d+)(\w+)', i).group(1))).replace("_", "") + '_' * i.endswith('_') if re.search('(\d+)(\w+)', i) else i for i in l)

Output:

'gg_kkkppp'

EDIT3

Solution without re module but with usual loops working for 2 digits. You could define functions:

def add_str(ind, st):
    if not st.endswith('_'):
        return st[ind:] * int(st[:ind])
    else:
        return st[ind:-1] * int(st[:ind]) + '_'

def collect(l):
    final_str =  


Wboy February 2016

Loop the list, check first entry for number, and then append the second digit onwards:

string=''
l = ['2g', 'k', '3p']
for entry in l:
    if len(entry) ==1:
        string += (entry)
    else:
        number = int(entry[0])
        for i in range(number):
            string += (entry[1:])


Avinash Raj February 2016

One-liner Regex way:

>>> import re
>>> st = '%2g%k%3p'
>>> re.sub(r'%|(\d*)(\w+)', lambda m: int(m.group(1))*m.group(2) if m.group(1) else m.group(2), st)
'ggkppp'

%|(\d*)(\w+) regex matches all % and captures zero or moredigit present before any word character into one group and the following word characters into another group. On replacement all the matched chars should be replaced with the value given in the replacement part. So this should loose % character.

or

>>> re.sub(r'%(\d*)(\w+)', lambda m: int(m.group(1))*m.group(2) if m.group(1) else m.group(2), st)
'ggkppp'


Rogalski February 2016

Assumes you are always printing single letter, but preceding number may be longer than single digit in base 10.

seq = ['2g', 'k', '3p']
result = ''.join(int(s[:-1] or 1) * s[-1] for s in seq)
assert result == "ggkppp"


Iron Fist February 2016

LATE FOR THE SHOW BUT READY TO GO

Another way, is to define your function which converts nC into CCCC...C (ntimes), then pass it to a map to apply it on every element of the list l coming from the split over %, the finally join them all, as follows:

>>> def f(s):
        x = 0
        if s:
            if len(s) == 1:
                out = s
            else:
                for i in s:
                    if i.isdigit():
                        x = x*10 + int(i)
                out = x*s[-1]

        else:
            out = ''
        return out

>>> st
'%4g%10k%p'
>>> ''.join(map(f, st.split('%')))
'ggggkkkkkkkkkkp'
>>> st = '%2g%k%3p'
>>> ''.join(map(f, st.split('%')))
'ggkppp'

Or if you want to put all of these into one single function definition:

>>> def f(s):
        out = ''
        if s:
            l = filter(None, s.split('%'))
            for item in l:
                x = 0
                    if len(item) == 1:
                        repl = item
                    else:
                        for c in item:
                            if c.isdigit():
                                x = x*10 + int(c)
                        repl = x*item[-1]
                    out += repl

        return out

>>> st
'%2g%k%3p'
>>> f(st)
'ggkppp'
>>> 
>>> st = '%4g%10k%p'
>>> 
>>> f(st)
'ggggkkkkkkkkkkp'
>>> st = '%4g%101k%2p'
>>> f(st)
'ggggkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkpp'
>>> len(f(st))
107

EDIT :

In case of the presence of _ where the OP does not want this character to be repeated, then the best way in my opinion is to go with

Post Status

Asked in February 2016
Viewed 2,541 times
Voted 12
Answered 5 times

Search




Leave an answer