优雅且节省代码的方式来计算循环中的属性而不使用“If ... Else Statements”

时间:2012-11-09 17:59:10

标签: python performance optimization

我有一个* .las格式的文件,我希望计算Return1,Return2,...,Return5的分数 我使用了If ... Else语句,但我希望了解是否有更优雅和代码保存的方法。在此先感谢您的帮助和提示。

    Return1 = 0
    Return2 = 0
    Return3 = 0
    Return4 = 0
    Return5 = 0
    count = 0
    for p in lasfile.File(inFile,None,'r'):
        count +=1
        if p.return_number == 1:
            Return1 += 1
        elif p.return_number == 2:
            Return2 += 1
        elif p.return_number == 3:
            Return3 += 1
        elif p.return_number == 4:
            Return4 += 1
        elif p.return_number == 5:
            Return5 += 1

3 个答案:

答案 0 :(得分:4)

您可以使用dict个计数器(在这种情况下,它也可以是一个列表)。 defaultdict非常方便:

from collections import defaultdict
returns = defaultdict(int)
count = 0
for p in lasfile.File(inFile, None, 'r'):
    count += 1
    returns[p.return_number] += 1

修改:我不确定DSM是否在Counter示例中发布单独的答案,因此我将在此处回复OP的问题:

  

@DSM:我可以结合Counter吗?例如:如果我想在同一时间计算p.return_number和p.scan_angle - Gianni

Counter将计算您给出的迭代中的值。可迭代应该是同源的。例如,如果scan_angle s可以取12等值,那么您不能对两者使用相同的Counter并获得正确的结果。如果值不重叠,您可以获得正确的结果,但您的代码会令人困惑且难以理解。我建议使用两个Counter:一个用于return_number,一个用于scan_angle。你可以使用相同的循环来轻松填充(和defaultdict的相同代表),但是如果你想压缩创建并将两个Counter填充到一个语句中,你将会需要像

这样的东西
from collections import Counter
rnc, sac = map(Counter, 
  zip(*((p.return_number, p.scan_angle) for p in lasfile.File(inFile,None,'r'))))

请注意,至少在Python 2上它会生成一个列表,因此所有数据都会在某个时刻保存在内存中。

然而,更简单的方法是:

  • 使用两个defaultdict s:

    returns, angles = defaultdict(int), defaultdict(int)
    for p in lasfile.File(inFile, None, 'r'):
         returns[p.return_number] += 1
         angles[p.scan_angle] += 1
         count += 1
    
  • 或在两个不同的文件读取中填写两个Counter

    fp = lasfile.File(inFile, None, 'r')
    returns = Counter(p.return_number for p in fp)
    fp = lasfile.File(inFile, None, 'r')
    angles = Counter(p.scan_angle for p in fp)
    

答案 1 :(得分:3)

使用字典:

return_counts = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
count = 0
for p in lasfile.File(inFile,None,'r'):
    count +=1
    if 1 <= p.return_number <= 5:
        return_counts[p.return_number] += 1

答案 2 :(得分:2)

假设p.return_number在1-5

范围内
Return = [0, 0, 0, 0, 0]
for p in lasfile.File(inFile,None,'r'):
    Return[p.return_number-1] += 1