Home > Blockchain >  Replace substring with variable of same name between two % signs without using replace or regex
Replace substring with variable of same name between two % signs without using replace or regex

Time:07-15

user = 'Peter'
location = 'Quahog'
friend = 'Stewie'
string = 'my name is %user% and i live in %location%, and my son is %friend%.'

The expected output would be

my name is Peter and i live in Quahog, and my son is Stewie.

The solution is expected to be O(N) time complexity, and there can any number of variables. The % symbols can also be inside words.

CodePudding user response:

I don't know why to do this, since there are functions ready for that, but... here it is, friend


def my_crazy_function(patterns:dict,text:str):
    IDENTIFIER = '%'
    inside_key = False 
    current_key = ''
    generated_text = ''
    for char in text:
        if char == IDENTIFIER:
            #means end the key
            if inside_key:
                #makes the replace 
                generated_text =patterns[current_key]
                #flips to False 
                inside_key = False 
                #reset current key
                current_key= ''
            else:
                #means start inside key
                inside_key = True 
            #the "%" char is ignored on string            
            continue 

        if inside_key:
            current_key =char 
        else:
            generated_text =char 
    return generated_text        


patterns ={
    'user':'Peter',
    'location':'Quahog',
    'friend':'Stewie'
}

string = 'my name is %user% and i live in %location%, and my son is %friend%.'

r = my_crazy_function(patterns,string)
print(r)

CodePudding user response:

I see two ways of doing it (without using regex, or python string methods), depending if you can put the variables in a dict or not. If you can, I will do it like this:

variables = {
    'user': 'Peter',
    'location': 'Quahog',
    'friend': 'Stewie'
}

string = 'my name is %user% and i live in %location%, and my son is %friend%.'
res = ''
pattern = None
for char in string:
    if char == '%':
        if pattern is None:
            pattern = ''
        else:
            res  = variables[pattern]
            pattern = None
    else:
        if pattern is None:
            res  = char
        else:
            pattern  = char
print(res)

The complexity is still O(N), because the string is iterated only once, and python dict get method is O(1).

Otherwise, if you are forced to use undeterminated independent variables, the solution will be like this:

user = 'Peter'
location = 'Quahog'
friend = 'Stewie'

string = 'my name is %user% and i live in %location%, and my son is %friend%.'
res = ''
pattern = None
for char in string:
    if char == '%':
        if pattern is None:
            pattern = ''
        else:
            res  = globals()[pattern]
            pattern = None
    else:
        if pattern is None:
            res  = char
        else:
            pattern  = char
print(res)

You should change the globals()[pattern] to locals()[pattern] if the variables are defined inside the function. In the case you dont know where the variables are defined, you can use eval(pattern), but i dont recomend that option, because enables code execution inside %%.

CodePudding user response:

The code below uses eval to find target variables. However, it should be carefully used because the use of eval can be problematic in many cases.

The phrase %% results in EOF error in this code. If you don't want it, check (idx_start 1) == idx_end.

user = 'Peter'
location = 'Quahog'
friend = 'Stewie'
string = 'my name is %user% and i live in %location%, and my son is %friend%.'
idx_start = None
idx_end = None

string_new = ''

for idx, ch in enumerate(string):
    if ch != '%':
        if idx_start is None:
            string_new = string_new   ch
    
    else:
        if idx_start is None:
            idx_start = idx
        else:
            idx_end = idx
            
            string_new  = eval(string[idx_start 1:idx_end])
            
            idx_start = None
            idx_end = None
string_new
> 'my name is Peter and i live in Quahog, and my son is Stewie.'

CodePudding user response:

Do not worry. Gilfoyle is here to help you out.

vocab_dict = {"user" : 'Peter',
              "location" : 'Quahog',
              "friend" : 'Stewie'}

sentence = 'my name is %user% and i live in %location%, and my son is %friend%.'

def fill_sentence(sentence, vocab_dict):
    special_char = "%"
    odd_flag = False
    
    word_found = ""
    generate_op = ""

    for char_i in sentence:
        if char_i == special_char and not odd_flag:
            odd_flag = True
            continue

        elif char_i == special_char and odd_flag:
            generate_op  = vocab_dict[word_found]
            odd_flag = False
            word_found = ""
            continue

        elif odd_flag:
            word_found = char_i
        else:
            generate_op = char_i

    return generate_op

        

fill_sentence(sentence, vocab_dict)

Output :

my name is Peter and i live in Quahog, and my son is Stewie.

CodePudding user response:

You can use globals() or replace all % ... % with { ... } and treat this string as a f-string and use all of the variables.

import re

string = 'my name is %user% and i live in %location%, and my son is %friend%.'

# approach_1
user = 'Peter'
location = 'Quahog'
friend = 'Stewie'

app1 = re.sub(r'%([^%]*)%', lambda x:  globals()[x.group(0)[1:-1]], string)
print(app1)

# approach_2
dct = {'user':'Peter', 'location':'Quahog', 'friend':'Stewie'}
rep_chr = re.sub(r'%([^%]*)%', r'{\1}', string)
print(rep_chr)
# my name is {user} and i live in {location}, and my son is {friend}.

print(rep_chr.format(**dct))
print(eval("f'{}'".format(rep_chr)))

Output:

my name is Peter and i live in Quahog, and my son is Stewie.
  • Related