Python 做重复的工作

Python 做重复的工作,python,list-comprehension,Python,List Comprehension,我有一个运行的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')] 然

我有一个运行的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
虽然这样做有效,但问题是对于列表中的每个迭代,函数都会执行两次。有更干净的方法吗?

试试这个:

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)]

您的
isValidFunction
应该返回True/False(顾名思义)。这样,您的列表理解就会变成:

valid = [num for num in phoneNumbers if isValidNumber(num, pattern)]
当您使用时,将
numbers
修改为生成器表达式,而不是列表理解(因为您对效率感兴趣):


我将更改您的有效性检查方法,只返回数字是否匹配,而不返回数字本身

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())]

这里有许多选项可供使用,包括
过滤器(无,映射(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循环,您可以精确地得到经过验证的数字

我喜欢一个更通用的电话号码验证器,您可以在其中传递模式。通过这种方式,您可以根据获得的数字格式使用任何模式。为了使
isValidNumber
过程更加一致,您可以根据数字是否有效将输出更改为True/False。由于该过程本身不修改数字,因此没有理由实际返回它。我认为在本例中,我可能会避免使用生成器表达式,只是按照它的使用方式。生成器将保持文件打开(并锁定),直到文件耗尽。我更喜欢尽可能快地访问文件,以避免潜在的损坏。
import re
numpat = re.compile(r'^\s*(\d{10})\s*$', re.MULTILINE)
filecontents = open('phonenumbers.txt', 'r').read()
validPhoneNumbers = numpat.findall(filecontents)