我写了一个简单的功能,将字母中的字母转换为他们的' leet'数字对应物。
def Leet(word):
letters = list(word.lower())
for n, letter, in enumerate(letters):
if letter == 'o':
letters[n]= '0'
elif letter == 'i':
letters[n]= '1'
elif letter == 'z':
letters[n]= '2'
elif letter == 'e':
letters[n]= '3'
elif letter == 'a':
letters[n]= '4'
elif letter == 's':
letters[n]= '5'
elif letter == 'g':
letters[n]= '6'
elif letter == 't':
letters[n]= '7'
elif letter == 'b':
letters[n]= '8'
return ''.join(letters)
所以当我输入'zit'
时,程序将返回'217'
。
我的问题是,如何更改它以便为我提供所有可能的排列('217'
,'2it'
,'z1t'
,'zi7'
,'21t'
等。)?我已经阅读了itertools
,但我对如何将其应用于我的功能感到难过。
答案 0 :(得分:5)
首先要注意的是,您可以缩短查找次数,如下所示:
REPLACE = { letter: str(index) for index, letter in enumerate('oizeasgtb') }
def Leet2(word):
letters = [ REPLACE.get(l, l) for l in word.lower() ]
return ''.join(letters)
REPLACE
看起来像:
{'a': '4', 'b': '8', 'e': '3', 'g': '6', 'i': '1',
'o': '0', 's': '5', 't': '7', 'z': '2'}
如果没有替换信,REPLACE.get(l,l)
会给你回信或原始信件。
第二个观察结果是你并不真正想要排列,这是排序的变化。 ' 217'的排列。是:
>>> [ ''.join(p) for p in permutations('217') ]
['217', '271', '127', '172', '721', '712']
您真正需要的是列表的产品,该列表编码给定角色位置的所有可能选择:
[('z', '2'), ('i', '1'), ('t', '7')]
如果我还显示一些可能没有有效替换字符的可能性列表,那么它的工作原理可能会更清楚。例如'red'
:
[('r',), ('e', '3'), ('d',)]
现在我们需要这些选项的字符串连接产品。把它们放在一起:
from itertools import product
def Leet2Combos(word):
possibles = []
for l in word.lower():
ll = REPLACE.get(l, l)
possibles.append( (l,) if ll == l else (l, ll) )
return [ ''.join(t) for t in product(*possibles) ]
print Leet2Combos('zit')
print Leet2Combos('red')
给出:
['zit', 'zi7', 'z1t', 'z17', '2it', '2i7', '21t', '217']
['red', 'r3d']
答案 1 :(得分:3)
使用itertools.product
。另外,我建议使用dict
进行映射,而不是级联if/elif
。
>>> from itertools import product
>>> LEET = { 'z': '2', 'i': '1', 't': '7' } # and all the others
>>> word = "zit"
>>> [''.join(letters) for letters in product(*({c, LEET.get(c, c)} for c in word))]
['zit', 'zi7', 'z1t', 'z17', '2it', '2i7', '21t', '217']
请注意LEET.get(c, c)
将从dict获取“leet”字母,或使用原始字母作为默认值。 {...}
用于制作这些对集,因此对于没有替换的字母没有重复。在旧版本的Python中,您可能不得不使用set([...])
。
相当复杂的product(*...)
行大致如下:
product(*({c, LEET.get(c, c)} for c in 'zit'))
==> product(*({'z', LEET.get('z', 'z')}, {'i', LEET.get('i', 'i')}, {'t', LEET.get('t', 't')}))
==> product(*({'z', '2'}, {'i', '1'}, {'t', '7'}))
==> product( {'z', '2'}, {'i', '1'}, {'t', '7'} )
产生所有这些字母的cartesian product及其替代品。
答案 2 :(得分:0)
一种方法是使用itertools.product,如你所提到的,它将执行列表的笛卡尔积。
问题是要有这个列表,每个组合,例如zit列表应该是:
[['z', '2'], ['i', '1'], ['t', '7']]
我的代码:
import itertools
def leet(word):
leet_matches = [['a', '4'],
['b' ,'8'],
['c'],
['d'],
['e', '3'],
['f'],
['g', '6'],
['h'],
['i', '1'],
['j'],
['k'],
['l'],
['m'],
['n'],
['o', '0'],
['p'],
['q'],
['r'],
['s', '5'],
['t', '7'],
['u'],
['v'],
['w'],
['x'],
['y'],
['z', '2']]
l = []
for letter in word:
for match in leet_matches:
if match[0] == letter:
l.append(match)
return list(itertools.product(*l))
print leet("zit")
请注意,使用列表(或元组)而不是Dict,您可以对一个字母进行多次替换,例如: " I"可以成为" 1"或"!"