使用string.translate()将不可打印的字符转换为点

时间:2009-11-25 23:59:30

标签: python code-golf

所以我之前已经完成了这项工作,这对于看似简单的任务来说是一个令人惊讶的丑陋代码。

目标是将任何不可打印的角色转换为(点)。出于我的目的,“可打印”会排除string.printable中的最后几个字符(换行符,制表符等)。这是用于打印旧的MS-DOS调试“十六进制转储”格式......或任何类似的东西(其他空格将破坏预期的转储布局)。

我知道我可以使用string.translate(),为了使用它,我需要一个翻译表。所以我使用string.maketrans()。这是我能想到的最好的:

filter = string.maketrans(
   string.translate(string.maketrans('',''),
   string.maketrans('',''),string.printable[:-5]),
   '.'*len(string.translate(string.maketrans('',''),
   string.maketrans('',''),string.printable[:-5])))

......这是一个难以理解的混乱(虽然它确实有效)。

从那里你可以使用类似的东西:

for each_line in sometext:
    print string.translate(each_line, filter)

......快乐。 (只要你不介意看。)

现在,如果我将这个可怕的表达式分解为单独的语句,它就更具可读性了:

ascii = string.maketrans('','')   # The whole ASCII character set
nonprintable = string.translate(ascii, ascii, string.printable[:-5])  # Optional delchars argument
filter = string.maketrans(nonprintable, '.' * len(nonprintable))

为了便于辨认,这样做很诱人。

但是,我一直认为必须有一种更优雅的方式来表达这一点!

4 个答案:

答案 0 :(得分:5)

这是使用列表理解的另一种方法:

filter = ''.join([['.', chr(x)][chr(x) in string.printable[:-5]] for x in xrange(256)])

答案 1 :(得分:4)

这里最广泛地使用“ascii”,但你明白了

>>> import string
>>> ascii="".join(map(chr,range(256)))
>>> filter="".join(('.',x)[x in string.printable[:-5]] for x in ascii)
>>> ascii.translate(filter)
'................................ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.................................................................................................................................'

如果我打高尔夫球,可能会使用这样的东西:

filter='.'*32+"".join(map(chr,range(32,127)))+'.'*129

答案 2 :(得分:1)

对于实际的代码 - 高尔夫,我想你完全避免使用string.maketrans

s=set(string.printable[:-5])
newstring = ''.join(x for x in oldstring if x in s else '.')

newstring=re.sub('[^'+string.printable[:-5]+']','',oldstring)

答案 3 :(得分:1)

我觉得这个解决方案很难看。它肯定比任何基于正则表达式的解决方案更有效。这是一个更短的解决方案。但只适用于python2.6:

nonprintable = string.maketrans('','').translate(None, string.printable[:-5])
filter = string.maketrans(nonprintable, '.' * len(nonprintable))