我编写了这段代码,将格式为“0(532)222 22 22”的字符串转换为整数,例如05322222222。
class Phone():
def __init__(self,input):
self.phone = input
def __str__(self):
return self.phone
#convert to integer.
def to_int(self):
return int((self.phone).replace(" ","").replace("(","").replace(")",""))
test = Phone("0(532) 222 22 22")
print test.to_int()
使用3种替换方法来解决这个问题感觉非常笨拙。我很好奇是否有更好的解决方案?
答案 0 :(得分:8)
p = "0(532) 222 22 22"
print ''.join([x for x in p if x.isdigit()])
请注意,如果要将其转换为int(就像标题中所建议的那样),您将“丢失”前导零。如果您想这样做,只需在int()
电话中打包上述内容即可。虽然(在我看来)电话号码作为字符串更有意义。
答案 1 :(得分:6)
在Python 2.6或2.7中,
(self.phone).translate(None,' ()')
将从电话字符串中删除任何空格或(
或)
。有关详细信息,请参阅Python 2.6 doc on str.translate。
在Python 3.x中,str.translate()采用映射(而不是如上所示的两个字符串)。因此,相应的片段类似于以下内容,使用str.maketrans()来生成映射
'(self.phone).translate(str.maketrans('','', '()-/ '))
有关详细信息,请参阅Python 3.1 doc on str.translate。
答案 2 :(得分:1)
如何使用正则表达式?
示例:
>>> import re
>>> num = '0(532) 222 22 22'
>>> re.sub('[\D]', '', num) # Match all non-digits ([\D]), replace them with empty string, where found in the `num` variable.
'05322222222'
ChristopheD提出的建议会很好,但效率不高。
以下是使用dis模块演示此示例的测试程序(有关详细信息,请参阅模块here上的Doug Hellman的PyMOTW)。
TEST_PHONE_NUM = '0(532) 222 22 22'
def replace_method():
print (TEST_PHONE_NUM).replace(" ","").replace("(","").replace(")","")
def list_comp_is_digit_method():
print ''.join([x for x in TEST_PHONE_NUM if x.isdigit()])
def translate_method():
print (TEST_PHONE_NUM).translate(None,' ()')
import re
def regex_method():
print re.sub('[\D]', '', TEST_PHONE_NUM)
if __name__ == '__main__':
from dis import dis
print 'replace_method:'
dis(replace_method)
print
print
print 'list_comp_is_digit_method:'
dis(list_comp_is_digit_method)
print
print
print 'translate_method:'
dis(translate_method)
print
print
print "regex_method:"
dis(phone_digit_strip_regex)
print
输出:
replace_method:
5 0 LOAD_GLOBAL 0 (TEST_PHONE_NUM)
3 LOAD_ATTR 1 (replace)
6 LOAD_CONST 1 (' ')
9 LOAD_CONST 2 ('')
12 CALL_FUNCTION 2
15 LOAD_ATTR 1 (replace)
18 LOAD_CONST 3 ('(')
21 LOAD_CONST 2 ('')
24 CALL_FUNCTION 2
27 LOAD_ATTR 1 (replace)
30 LOAD_CONST 4 (')')
33 LOAD_CONST 2 ('')
36 CALL_FUNCTION 2
39 PRINT_ITEM
40 PRINT_NEWLINE
41 LOAD_CONST 0 (None)
44 RETURN_VALUE
phone_digit_strip_list_comp:
3 0 LOAD_CONST 1 ('0(532) 222 22 22')
3 STORE_FAST 0 (phone)
4 6 LOAD_CONST 2 ('')
9 LOAD_ATTR 0 (join)
12 BUILD_LIST 0
15 DUP_TOP
16 STORE_FAST 1 (_[1])
19 LOAD_GLOBAL 1 (test_phone_num)
22 GET_ITER
23 FOR_ITER 30 (to 56)
26 STORE_FAST 2 (x)
29 LOAD_FAST 2 (x)
32 LOAD_ATTR 2 (isdigit)
35 CALL_FUNCTION 0
38 JUMP_IF_FALSE 11 (to 52)
41 POP_TOP
42 LOAD_FAST 1 (_[1])
45 LOAD_FAST 2 (x)
48 LIST_APPEND
49 JUMP_ABSOLUTE 23
52 POP_TOP
53 JUMP_ABSOLUTE 23
56 DELETE_FAST 1 (_[1])
59 CALL_FUNCTION 1
62 PRINT_ITEM
63 PRINT_NEWLINE
64 LOAD_CONST 0 (None)
67 RETURN_VALUE
translate_method:
11 0 LOAD_GLOBAL 0 (TEST_PHONE_NUM)
3 LOAD_ATTR 1 (translate)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 1 (' ()')
12 CALL_FUNCTION 2
15 PRINT_ITEM
16 PRINT_NEWLINE
17 LOAD_CONST 0 (None)
20 RETURN_VALUE
phone_digit_strip_regex:
8 0 LOAD_CONST 1 ('0(532) 222 22 22')
3 STORE_FAST 0 (phone)
9 6 LOAD_GLOBAL 0 (re)
9 LOAD_ATTR 1 (sub)
12 LOAD_CONST 2 ('[\\D]')
15 LOAD_CONST 3 ('')
18 LOAD_GLOBAL 2 (test_phone_num)
21 CALL_FUNCTION 3
24 PRINT_ITEM
25 PRINT_NEWLINE
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
翻译方法将是最有效的,但依赖于py2.6 +。正则表达式的效率略低,但更兼容(我认为对你有要求)。原始替换方法将为每次替换添加6个附加指令,而所有其他指令将保持不变。
在旁注中,将您的电话号码存储为字符串以处理前导零,并在需要时使用电话格式化程序。相信我,以前咬过我。
答案 3 :(得分:-1)
SilentGhost:dis.dis
演示了潜在的概念/执行复杂性。毕竟,OP抱怨原来的替代链太“笨拙”,不太“慢”。
我建议不要使用不可避免的正则表达式;他们只是增加概念开销和速度惩罚。使用translate()
这里是恕我直言,这是一个错误的工具,并没有像原始替代链那样在概念上简单和通用。
所以你说tamaytoes,我说tomahtoes:原始解决方案在清晰度和通用性方面非常好。它根本不笨拙。为了使其更加密集和更具参数化,请考虑将其更改为
phone_nr_translations = [
( ' ', '', ),
( '(', '', ),
( ')', '', ), ]
def sanitize_phone_nr( phone_nr ):
R = phone_nr
for probe, replacement in phone_nr_translations:
R = R.replace( probe, replacement )
return R
在这个特殊的应用程序中,当然,你真正想做的只是取消任何不需要的字符,所以你可以简化这个:
probes = ' ()'
def sanitize_phone_nr( phone_nr ):
R = phone_nr
for probe in probes:
R = R.replace( probe, '' )
return R
想到它,我不太清楚你为什么要把手机nr变成一个整数 - 这只是错误的数据类型。这可以通过以下事实来证明:至少在移动网络中,+
和#
可能更多是拨号字符串中的有效字符(dial,string-see?)。
但除此之外,清理用户输入手机nr以获得规范化和安全的表示是一个非常非常有效的问题 - 只是我觉得你的方法太具体了。为什么不将消毒方法重新编写成非常通用的东西而不会变得更复杂?毕竟,如何确保您的用户永远不会在该Web表单字段中输入其他异常字符?
所以你想要的实际上不是 dis - 允许特定字符(在unicode 5.1中有大约十万个定义的代码点,那么如何赶上这些?),但是对于允许那些在拨号字符串中被认为合法的字符。你可以用正则表达式做到这一点......
from re import compile as _new_regex
illegal_phone_nr_chrs_re = _new_regex( r"[^0-9#+]" )
def sanitize_phone_nr( phone_nr ):
return illegal_phone_nr_chrs_re.sub( '', phone_nr )
...或有一套:
legal_phone_nr_chrs = set( '0123456789#+' )
def sanitize_phone_nr( phone_nr ):
return ''.join(
chr for chr in phone_nr
if chr in legal_phone_nr_chrs )
最后一节可以写在一行上。这个解决方案的缺点是你可以迭代Python中的输入字符,而不是使用str.replace()
或者正则表达式提供的潜在的调速器C遍历。但是,性能在任何情况下都取决于预期的使用模式(我确定你首先截断你的手机,对吧?那么那些将要处理的是很多小字符串,而不是很少的大字符串。)
请注意以下几点:我力求清晰,这就是为什么我试图避免过度使用缩写。 chr
为character
,nr
为number
,返回值为R
(更有可能是,{,1}}标准库)在我的风格书中。编程是关于理解和完成事情,而不是编写程序员编写接近gzip空间效率的代码。现在看,最后的解决方案确实完成了OP设法完成的工作(以及更多),... ...
retval
......如果需要两行代码,而OP的代码......
legal_phone_nr_chrs = set( '0123456789#+' )
def sanitize_phone_nr( phone_nr ): return ''.join( chr for chr in phone_nr if chr in legal_phone_nr_chrs )
......几乎不能压缩到四行以下。看看严格的OOP解决方案给你带来了哪些额外的包袱?我相信它大部分时间都可以被排除在外。