简体   繁体   中英

How to replace strings in list from a dictionary with all possible combinations

I want to replace a string named test1 which is listed in lst using a dictionary named gRep1Map . It needs to return all possible combinations using the characters in gRep1Map . I get an output, but not the one i want to. Can't really seem to find a way how to achieve this.

Here is my code.

text = "Test1"

#Create dictionary
gReplMap = { 'a': '@', 'e': '3', 'i': '1', 'o': '0', 't': '+',
             'A': '@', 'E': '3', 'I': '1', 'O': '0', 'T': '+',
}

lst = []

for old, new in gReplMap.items():
    text = text.replace(old, new)
    lst.append(text)
    print(lst)

The output is like below.

['Test1']
['Test1', 'T3st1']
['Test1', 'T3st1', 'T3st1']
['Test1', 'T3st1', 'T3st1', 'T3st1']
['Test1', 'T3st1', 'T3st1', 'T3st1', 'T3s+1']
['Test1', 'T3st1', 'T3st1', 'T3st1', 'T3s+1', 'T3s+1']
['Test1', 'T3st1', 'T3st1', 'T3st1', 'T3s+1', 'T3s+1', 'T3s+1']
['Test1', 'T3st1', 'T3st1', 'T3st1', 'T3s+1', 'T3s+1', 'T3s+1', 'T3s+1']
['Test1', 'T3st1', 'T3st1', 'T3st1', 'T3s+1', 'T3s+1', 'T3s+1', 'T3s+1', 'T3s+1']
['Test1', 'T3st1', 'T3st1', 'T3st1', 'T3s+1', 'T3s+1', 'T3s+1', 'T3s+1', 'T3s+1', '+3s+1']

But i want it to be like this.

['test1', 'tes+1', 't3st1', 't3s+1', '+est1', '+es+1', '+3st1', '+3s+1']

Anyone who could help?

You should not be iterating through the dictionary but through the letters of the text. Here is a solution that doesn't use itertools.

text = "Test1"
gReplMap = { 'a': '@', 'e': '3', 'i': '1', 'o': '0', 't': '+',
         'A': '@', 'E': '3', 'I': '1', 'O': '0', 'T': '+'}
lst = [text]
#Iterate through each letter in each word in lst and update the lst
for string in lst:
    for letter in string:
        if letter in gReplMap:
            new_string = string.replace(letter, gReplMap[letter])
            if new_string not in lst:
                lst.append(new_string)
print(lst)

(a rare case of usefulness of reduce ...)

from itertools import combinations
from functools import reduce

out = {
    reduce(lambda x, y: x.replace(y[0], y[1]), repls, text)
    for n in range(len(gReplMap) + 1)
    for repls in combinations(gReplMap.items(), n)
}

Produces:

>>> out
{'+3s+1', '+3st1', '+es+1', '+est1', 'T3s+1', 'T3st1', 'Tes+1', 'Test1'}

If you prefer to see the distinct values in the order they were generated, use a dict (which has insertion order) and make a list of it:

out = list({
    reduce(lambda x, y: x.replace(y[0], y[1]), repls, text): 1
    for n in range(len(gReplMap) + 1)
    for repls in combinations(gReplMap.items(), n)
})

Then:

>>> out
['Test1', 'T3st1', 'Tes+1', '+est1', 'T3s+1', '+3st1', '+es+1', '+3s+1']

Note: in the desired result of your original question, all the variants of 'test1' seem lowercase, but neither your sample code or the text of the question seems to specify that. Of course, use .lower() after reduce if that's what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM