我有一个正在运行的python脚本,它读入一个电话号码文件。其中一些电话号码无效。
import re
def IsValidNumber(number, pattern):
isMatch = re.search(pattern, number)
if isMatch is not None:
return number
numbers = [line.strip() for line in open('..\\phoneNumbers.txt', 'r')]
然后我使用另一个列表理解来过滤掉不好的数字:
phonePattern = '^\d{10}$'
validPhoneNumbers = [IsValidNumber(x, phonePattern) for x in phoneNumbers
if IsValidNumber(x, phonePattern) is not None]
for x in validPhoneNumbers:
print x
由于格式化,第二个列表理解跨越了两行。
问题是虽然IsValidNumber只应该在匹配有效时返回数字,但在无效匹配时它也会返回'None'。所以我不得不修改第二个列表理解包括:
if IsValidNumber(x, phonePattern) is not None
虽然这有效,但问题是对于列表中的每次迭代,函数执行两次。这样做有更清洁的方法吗?
答案 0 :(得分:4)
你的isValidFunction
应该返回True / False(顾名思义)。这样你的列表理解就变成了:
valid = [num for num in phoneNumbers if isValidNumber(num, pattern)]
当你在这里时,将numbers
修改为生成器表达式而不是列表推导(因为你对效率感兴趣):
numbers = (line.strip() for line in open("..\\phoneNumbers.txt"))
答案 1 :(得分:2)
试试这个:
validPhoneNumbers = [x for x in phoneNumbers if isValidNumber(x, phonepattern)]
由于isValidNumber
返回的传入号码与传入的号码相同,因此您实际上并不需要该号码。你只需要知道一个数字就完全返回了(这个数字是有效的)。
您也可以将整个事情与:
结合起来validPhoneNumbers = [x.strip() for x in open('..\\phonenumbers.txt', 'r') if isValidNumber(x.strip(), phonePattern)]
答案 2 :(得分:2)
我会更改您的有效性检查方法,只是返回数字是否匹配,但不返回数字本身。
def is_valid_number(number):
return re.search(r'^\d{10}$', number)
然后你可以过滤掉第一个列表理解中的无效数字:
numbers = [line.strip() for line in open('..\\phoneNumbers.txt', 'r')
if is_valid_number(line.strip())]
答案 3 :(得分:0)
此处有许多选项,包括filter(None, map(isValidNumber, lines))
。效率最高的可能是让正则表达式完成所有工作:
import re
numpat = re.compile(r'^\s*(\d{10})\s*$', re.MULTILINE)
filecontents = open('phonenumbers.txt', 'r').read()
validPhoneNumbers = numpat.findall(filecontents)
这样就不需要Python循环了,你可以得到经过验证的数字。