2016-11-13 77 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