-2

我有一个使用 GyPython 组件的简单脚本,用于 Rhino/Grasshopper。目标是将每小时的天气数据(仅记录几个小时)分配给小时。如果没有测量,则返回 0。它应该像这样工作(具有相似值的示例):

hoursList = [hr1,hr2,hr3,hr4,hr5,hr6]
measuredList = [hr2,hr3,hr6]
recordList = [wData1,wData2,wData3]
finalList = []    

def assignData(i,y):        
    for i < len(leadList):            
        if hoursList[i] == measuredList[y]:                
            finalList.append(recordList[y])                
            i += 1
            y += 1                
        else:                
            finalList.append(0)                
            i += 1    
        assignData(i,y)    

i = 0
y = 0    
assignData(i,y)

应该返回_

[0,wData1,wData2,0,0,wData3]

这种情况的结果finalList(添加换行符以提高可读性)

[0, 'wData1', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 'wData1', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 'wData2', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3', 0, 0, 'wData3', 'wData3',
 0, 'wData3', 'wData3']

当我尝试在大型数据列表(大约 43000 个值)上运行此代码时,它在大约 7000 次迭代后崩溃。我检查了 sys.getrecursionlimit,它是 2147483647。有什么想法可以完成这项工作吗?

4

1 回答 1

2

分析

我猜那len(leadList)是你给出的 43000 数字。我会打电话给这个limit

请注意您的循环是如何工作的:对于i“输入 i”到 范围内的每个值limit,这会处理一个项目,递增i(可能还有y),然后重复。因此,您的顶级调用i=0将产生一个调用assignData(1, 0)(假设失败)并等待它完成。然后它会回到循环的顶部,使用 i=1,并继续……最终limit连续产生递归调用。

该初始调用现在将工作范围(1,限制),生成调用,limit-1其中第一个调用将生成limit-2调用,依此类推。每个级别都会产生另一个具有大扇出的级别。

简而言之,你产生的电话比我想象的要多得多。随着你的增加,总数增长得相当快limit

我怀疑您的问题finalList只是超出了可用内存,因为这些调用中的每一个都附加了一个元素。

调查

将基本调试语句插入到您的代码中:

def assignData(i, y):
    print "ENTER", i, y, finalList
    for i < len(leadList):
        ...

因此,您可以看到呼叫的进度。

修理

我怀疑您是否需要这种双重嵌套的递归堆栈。事实上,我认为递归不会给你带来任何好处。看起来您只需要遍历列表一次,找到实际对应的时间,否则填写 0。摆脱调用,使用for适当的来控制 的值i,并酌情削减代码。

def assignData():
    y = 0        
    for i in range(0, len(leadList)):            
        if hoursList[i] == measuredList[y]:                
            finalList.append(recordList[y])                
            y += 1                
        else:                
            finalList.append(0)

更好的解决方案

如果您只需要匹配时间的记录,则可以更直接。建立一个字典来索引时间的测量值。

meas = dict(zip(measuredList, recordList)

现在,编写一个列表推导来在字典中没有的任何时间插入 0。

finalList = [meas[time] if time in meas else 0
                for time in hourslist]

如果我正确阅读了您的问题,那是您的总体目标。

于 2017-08-02T19:20:08.780 回答