列表理解做重复工作
List comprehension doing duplicate work
我有一个 运行 python 脚本,它读取 phone 个数字的文件。其中一些 phone 号码无效。
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 应该只 return 如果匹配有效,它也会 return s 'None' 无效匹配。所以我不得不修改第二个列表理解以包括:
if IsValidNumber(x, phonePattern) is not None
虽然这可行,但问题是对于列表中的每次迭代,该函数都会执行两次。是否有更简洁的方法来执行此操作?
试试这个:
validPhoneNumbers = [x for x in phoneNumbers if isValidNumber(x, phonepattern)]
由于 isValidNumber
returns 与传入的号码相同,未经修改,您实际上并不需要该号码。您只需要知道返回了一个数字(意味着该数字有效)。
您也可以将整个事情与以下内容结合起来:
validPhoneNumbers = [x.strip() for x in open('..\phonenumbers.txt', 'r') if isValidNumber(x.strip(), phonePattern)]
您的 isValidFunction
应该 return True/False(顾名思义)。这样你的列表理解就变成了:
valid = [num for num in phoneNumbers if isValidNumber(num, pattern)]
当你这样做时,将 numbers
修改为生成器表达式而不是列表理解(因为你对效率感兴趣):
numbers = (line.strip() for line in open("..\phoneNumbers.txt"))
我会将您的有效性检查方法更改为简单地 return 号码是否匹配,而不是 return 号码本身。
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())]
这里有很多选项可供使用,包括 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 循环,并且您可以准确地获得经过验证的数字。
我有一个 运行 python 脚本,它读取 phone 个数字的文件。其中一些 phone 号码无效。
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 应该只 return 如果匹配有效,它也会 return s 'None' 无效匹配。所以我不得不修改第二个列表理解以包括:
if IsValidNumber(x, phonePattern) is not None
虽然这可行,但问题是对于列表中的每次迭代,该函数都会执行两次。是否有更简洁的方法来执行此操作?
试试这个:
validPhoneNumbers = [x for x in phoneNumbers if isValidNumber(x, phonepattern)]
由于 isValidNumber
returns 与传入的号码相同,未经修改,您实际上并不需要该号码。您只需要知道返回了一个数字(意味着该数字有效)。
您也可以将整个事情与以下内容结合起来:
validPhoneNumbers = [x.strip() for x in open('..\phonenumbers.txt', 'r') if isValidNumber(x.strip(), phonePattern)]
您的 isValidFunction
应该 return True/False(顾名思义)。这样你的列表理解就变成了:
valid = [num for num in phoneNumbers if isValidNumber(num, pattern)]
当你这样做时,将 numbers
修改为生成器表达式而不是列表理解(因为你对效率感兴趣):
numbers = (line.strip() for line in open("..\phoneNumbers.txt"))
我会将您的有效性检查方法更改为简单地 return 号码是否匹配,而不是 return 号码本身。
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())]
这里有很多选项可供使用,包括 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 循环,并且您可以准确地获得经过验证的数字。