2016-11-13 73 views
0

這裏有兩個python函數將數據從一個文件傳輸到另一個文件。源文件和目標文件都具有相同數量的對象,但具有不同的數據。Python中多循環邏輯和速度優化?

def getBlock(rigObj, objName): 
    rigObj.seek(0) 
    Tag = False 
    block = "" 
    for line in rigObj: 
     if line.find("ObjectAlias " + str(objName) + "\n") != -1: 
      for line in rigObj: 
       if line.find("BeginKeyframe") != -1: 
        Tag = True 
       elif line.lstrip().startswith("0.000 ") and line.rstrip().endswith("default"): 
        Tag = False 
        break 
       elif Tag: 
        block += line 
    return (block) 

def buildScene(sceneObj, rigObj, objList): 
    sceneObj.seek(0) 
    rigObj.seek(0) 
    newscene = "" 
    for line in sceneObj: 
     newscene += line 
     for obj in objList: 
      if line.find("ObjectAlias " + obj + "\n") != -1: 
       Tag = True 
       for line in sceneObj: 
        if line.find("BeginKeyframe") != -1: 
         newscene += line 
         newscene += getBlock(rigObj, obj) 
         Tag = False 
        elif line.lstrip().startswith("0.000 ") and line.rstrip().endswith("default"): 
         newscene += line 
         Tag = True 
         break 
        elif Tag: 
         newscene += line 
    return (newscene) 

getBlock是用於從rigobj獲取數據的子功能;
buildScene是我的主要功能,它有三個參數:
第一個參數(sceneobj)是我想要放入數據的文件;
第二個參數(rigobj)是我從中獲取數據的文件;
第三個參數(objlist)是要傳輸什麼對象數據的列表。

到目前爲止,函數,它的工作,唯一的問題是有點慢的(sceneobj < 10MB,rigobj < 2MB,objlist < 10個對象),我不知道是否有代碼是一個邏輯問題,我應該先循環sceneObj還是先循環objList?它會影響速度嗎?

UPDATE:
兩個sceneObj和rigObj有這樣類似的數據:

lines 
BeginObject    
lines      
ObjectAlias xxx   #--> object in transfer list 
lines      
BeginKeyframe 10 12  
    -9.000 4095 default  #--> transfer begins 
    lines     #--> transfer from rigObj to sceneObj and override lines in sceneObj 
    -8.000 63 default  #--> same 
    lines     #--> same 
    -7.000 63 default  #--> same 
    lines     #--> same 
    -1.000 63 default  #--> same 
    lines     #--> transfer ends 
    0.000 -1 default   
    lines     
EndKeyframe    
EndMotion     
lines      
EndObject 

的數據要被轉移和overrided只有線bewteen BeginKeyframe0.000 -1默認任何指定的對象(由objList)

+0

你可以添加分析器結果和輸入數據的例子嗎? – Arnial

+0

@Arnial更新了我的文章 – Tian

+0

rigObj可能多次使用相同的ObjectAlias但數據不同? – Arnial

回答

0

最明顯的優化是索引getBlock函數的數據,所以你將能夠尋求所需的位置,而不是始終從頭開始解析完整文件。

像這樣:

def create_rig_index(rig_obj): 
    """ This function creates dict of offsets for specific ObjectAlias 
     Example: 
       data: 
        line with offset 100: ObjectAlias xxx 
        more lines 
        line with offset 200: ObjectAlias yyy 
        more lines 
        line with offset 300: ObjectAlias xxx 
        more lines 

       result will be: 
        xxx: [100, 300] 
        yyy: [200] 
    """ 
    idx = defaultdict(list) 
    position = 0 
    for line in rig_obj: 
     strip_line = line.strip() 
     if strip_line.startswith("ObjectAlias"): 
      obj_name = strip_line.split()[1] 
      idx[ obj_name ].append(position) 

     # unfortunately python prevent `tell` calls during iteration. 
     position += len(bytes(line, 'utf-8')) 
     # if data guaranteed to be ascii only its possible to use len(line) 
     # or you can write custom line generator on top of read function. 
    return idx; 

def getBlock(rigObj, rigIdx, objName): 
    """ same as your getBlock, but uses precalculated offsets""" 
    block = "" 
    for idx in rigIdx[ objName ]: 
     rigObj.seek(idx) 
     Tag = False 
     for line in rigObj: 
      if line.find("BeginKeyframe") != -1: 
       Tag = True 
      elif line.lstrip().startswith("0.000 ") and line.rstrip().endswith("default"): 
       break 
      elif Tag: 
       block += line 

    return (block) 

在建立場景的方法,你應該爲循環運行之前創建rig_index,並在getBlock功能使用此索引。

+0

感謝您的幫助。從你的意思,我的代碼沒有任何邏輯問題,最浪費時間的部分是getBlock搜索(我完全同意這個),對吧?我有一個關於'如果line.find(「ObjectAlias」+ obj +「\ n」)!= -1:'在** buildScene **中的問題,如果一行不能以** ObjectAlias **開頭,代碼仍然會在objList的obj中使用? – Tian

+0

是的,即使行不是以「ObjectAlias」開始,它也會遍歷'objList'。 – Arnial

+0

你也可以使用''ObjectAlias「+ obj +」\ n「而不是'line.find(」ObjectAlias「+ obj +」\ n「)!= -1'。 Python文檔要求不要使用'in'運算符而不是[find](https://docs.python.org/3.3/library/stdtypes.html#str.find)。 – Arnial