Python中的多循环逻辑和速度优化?

2024-09-28 03:19:44 发布

您现在位置: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获取数据的子函数;
构建场景是我的主要功能,它有三个参数:
第一个参数(sceneobj)是我要将数据放入的文件;
第二个参数(rigobj)是我从中获取数据的文件;
第三个参数(objlist)是要传输的对象数据的列表。你知道吗

到目前为止,函数完成了它的工作,唯一的问题是有点慢(sceneobj<;10MB,rigobj<;2MB,objlist<;10个对象),我不确定代码中是否有逻辑问题,我应该先循环sceneobj还是先循环objlist?会影响速度吗?你知道吗

更新:
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

要传输和覆盖的数据只有BeginKeyframe0.000之间的行-任何指定对象的默认值(按objList)


Tags: 文件数据对象indefaultforiftag
1条回答
网友
1楼 · 发布于 2024-09-28 03:19:44

最明显的优化是为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)

在buildScene方法中,您应该在运行for循环之前创建rig\u索引,并在getBlock函数中使用此索引。你知道吗

相关问题 更多 >

    热门问题