用字母替换数字并提供所有排列

Replace numbers with letters and offer all permutations

在将数字转换为视觉上可能相似的字母时,我需要确定包含数字的字符串的所有可能字母组合。

使用词典:

number_appearance = {
       '1': ['l', 'i'],
       '2': ['r', 'z'],
       '3': ['e', 'b'],
       '4': ['a'],
       '5': ['s'],
       '6': ['b', 'g'] ,
       '7': ['t'],
       '8': ['b'], 
       '9': ['g', 'p'],
       '0': ['o', 'q']} 

我想编写一个接受输入并创建所有可能的字母组合的函数。例如:

text = 'l4t32'

def convert_numbers(text):
      return re.sub('[0-9]', lambda x: number_appearance[x[0]][0], text)

我希望输出是一个包含所有可能排列的列表:

['later', 'latbr', 'latbz', 'latez]

如果您只是从 number_appearance 中获取每个列表中的第一个字母,那么上面的函数就可以工作,但我正在尝试找出遍历所有可能组合的最佳方法。任何帮助将不胜感激!

def convert_num_appearance(text):
    string_characters = [character for character in text]
    
    all_items = []

    for item in string_characters:
        if re.search('[a-zA-Z]', item):
           all_items.append([item])
        elif re.search('\d', item):
           all_items.append(number_appearance[item])

    return [''.join(elem) for elem in itertools.product(*all_items)]

我会这样分解问题:

  1. 首先,创建一个可以对给定的一组替换字母进行替换的函数。我的输入规范是一个字母序列,其中第一个字母是 '0' 字符的替换,接下来是 1 等。这允许我使用该序列中的索引来确定被替换的字符,同时生成普通序列而不是字典或其他复杂结构。要进行替换,我将使用原始字符串的内置 translate 方法。这需要一个如 in the documentation 所述的字典,我可以使用字典理解或提供的辅助方法 str.maketransstr 类型的静态方法)轻松构建它。

  2. Use itertools.product 生成这些序列。

  3. 使用列表理解为每个序列应用替换。

因此:

from itertools import product

def replace_digits(original, replacement):
    # translation = {ord(str(i)): c for i, c in enumerate(replacement)}
    translation = str.maketrans('0123456789', ''.join(replacement))
    print(translation)
    return original.translate(translation)

replacements = product(
   ['o', 'q'], ['l', 'i'], ['r', 'z'], ['e', 'b'], ['a'],
   ['s'], ['b', 'g'] , ['t'], ['b'], ['g', 'p']
)

[replace_digits('14732', r) for r in replacements]

(您会注意到结果中有重复项;这是因为对输入中未出现的符号进行了变体替换。)

作为对您自己答案的升级,我建议如下:

    def convert_numbers(text):
        all_items = [number_appearance.get(char, [char]) for char in text]
        return [''.join(elem) for elem in itertools.product(*all_items)]

改进之处在于:

  • 它不会将文本转换为列表(没有必要)
  • 你不需要正则表达式
  • 如果您决定还想在数字之上添加其他字符,它仍然有效