迭代嵌套子列表

时间:2014-04-23 17:52:26

标签: python list python-2.7 dynamic arcpy

我正在尝试创建一个可用于处理数据块的运行列表,因为必须在第一批处理完成后运行单独的函数。我把那部分放下了。我遇到的问题是创建运行列表 我有一个处理区域列表,如果其中一个区域与已经测试过的区域重叠,则需要将其移动到下一个子列表。然后将以相同的方式测试该子列表。当最后一个子列表的长度为1时,迭代将停止。

实施例

  1. 初始列表:[1,2,3,4,5,6](3& 4与2重叠; 5& 6重叠3& 4)
  2. 测试#1输出:[[1,2],[3,4,5,6]]
  3. 测试#2输出:[[1,2],[3,4],[5,6]]
  4. 当前代码

    def containTest(a, b):
        return not set(a).isdisjoint(b)
    
    def getValueList(inputTable, field):
        valueSet = set()  # set to hold unique values
        # use data access search cursor combined with, 'with'
        with arcpy.da.SearchCursor(inputTable, field) as values:
            # iterate through all values returned by Search Cursor
            for value in values:
                # Add value to set. If the value is not present,
                # it will be added. If it is present, the set will not
                # allow duplicates.
                valueSet.add(value[0])
        # sort and return list of values
        return sorted(valueSet)
    
    
    import sys
    import os
    import traceback
    
    # ArcGIS initialization
    from arcpy.sa import *  # for ArcPy map algebra
    import arcpy
    arcpy.SetProduct("ArcInfo")
    arcpy.CheckOutExtension("Spatial")  # spatial analyst license
    
    # Geoprocessing error exception
    from arcpy import ExecuteError as GPError
    
    # ENV setup
    arcpy.env.overwriteOutput = True
    
    try:  
        # <get arguments from the command line here>
        vpupth = r'C:\TmpSS\NHDPlus06'
        workp = vpupth + os.sep + "RemoveSinks"  # (type Workspace) Path where results written into folders for each sink
        sinktbl = r"C:\TmpSS\NHDPlus06\RemoveSinks\sinks_00.shp"  # list of areas to process, integers are in the "GridCode" field
    
        # vrbls to identify first times through loops
        firsttime = True
    
        # Copy sinktbl to in_memory
        arcpy.CopyFeatures_management(sinktbl, "in_memory\sinktbl")
        sinktbl = "in_memory\sinktbl"
    
        # Make Layers of needed feature classes
        arcpy.MakeFeatureLayer_management(vsink, "in_memory\lyrSink")
        arcpy.MakeFeatureLayer_management(vcatch, "in_memory\lyrCatch")
    
        runlist = [[], []]
        chkdupes = set()
    
        sinknum = 1
        with arcpy.da.SearchCursor(sinktbl, ("GridCode")) as sinkrows:
            for sinkrow in sinkrows:
                sinkid = sinkrow[0]
    
                print "Processing Sink " + str(sinknum) + " GridCode = " + str(sinkid)
    
                # Select the sink specified in the table row
                arcpy.SelectLayerByAttribute_management("in_memory\lyrSink", "NEW_SELECTION", "GridCode = %s" % sinkid)
                # Write out to shapefile sinkprj
                arcpy.CopyFeatures_management("in_memory\lyrSink", "in_memory\sinkprj")
                # Select the catchment the sink falls within
                arcpy.SelectLayerByLocation_management("in_memory\lyrCatch", "INTERSECT", "in_memory\lyrSink", "", "NEW_SELECTION")
                # Select the catchments surrounding the catchment containing sink
                arcpy.SelectLayerByLocation_management("in_memory\lyrCatch", "BOUNDARY_TOUCHES", "in_memory\lyrCatch", "", "NEW_SELECTION")
                # Write inner catchments out to shapefile catchi
                arcpy.CopyFeatures_management("in_memory\lyrCatch", "in_memory\catchi")
    
                # Select another tier of catchments surrounding the selected catchments (second tier out from sink)
                arcpy.SelectLayerByLocation_management("in_memory\lyrCatch", "BOUNDARY_TOUCHES", "in_memory\lyrCatch", "", "NEW_SELECTION")
                # Write outer catchments out to shapefile catcho
                arcpy.CopyFeatures_management("in_memory\lyrCatch", "in_memory\catcho")    
                catchlist = set(getValueList("in_memory\catcho", "GridCode"))
    
                i = 0
                if firsttime is True:
                    chkdupes |= catchlist
                    firsttime = False
                    runlist[i].append(sinkid)
                    print "First time copy complete"
                    i += 1
                else:
                    if containTest(chkdupes, catchlist):
                        print "catchlist exists, moving sink to next iteration"
                        runlist[i + 1].append(sinkid)
                    else:
                        print "sink does not exist in catchment list"
                        chkdupes |= catchlist
                        print "added to round one"
                        runlist[i].append(sinkid)
                    i += 1
    
                del catchlist
                arcpy.Delete_management("in_memory\catcho")
                arcpy.Delete_management("in_memory\catchi")
                sinknum += 1
    
            print runlist
    
    except arcpy.ExecuteError:
        # Get the tool error messages
        msgs = arcpy.GetMessages(2)
        # Return tool error messages for use with a script tool
        arcpy.AddError(msgs)
        # Print tool error messages for use in Python/PythonWin
        print msgs
    
    except:
        # Get the traceback object
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        # Concatenate information together concerning the error into a message string
        pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
        msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
    
        # Return python error messages for use in script tool or Python Window
        arcpy.AddError(pymsg)
        arcpy.AddError(msgs)
    
        # Print Python error messages for use in Python / Python Window
        print pymsg + "\n"
        print msgs
    finally:
      # Clean up here (delete cursors, temp files)
      pass  
    

    感谢所有看一看,非常感谢帮助。我觉得有一种先进的方法来执行这项任务,但我缺乏知识使我无法看到解决方案。

1 个答案:

答案 0 :(得分:0)

问题有点难以理解,但由于我遇到同样的问题,我实际上知道你想要什么。您希望将多个元素排序到框中,其中较高编号框中的元素仅依赖于较低编号框中的元素,并且框中的框尽可能少。您的应用程序是GIS,很可能是重叠图像区域的绘制。

解决方案并不是很困难。我的输入数据结构是一个条目列表。每个条目都有一个元素id和该元素的依赖关系列表(此元素所依赖的元素的ID)。输出是元素id的集合列表,其中每个集合描述了一组可以同时处理/绘制的元素。

解决方案是迭代的:通过所有没有依赖关系的元素减少可用元素列表,并将所有这些元素放入一个新框中。然后通过删除刚放入框中的元素的所有依赖项来减少其余元素的依赖关系。 difference函数以及列表推导非常方便。

代码示例是:

def order_by_dependency(input):
    # start with empty output
    output = []

    # in a loop
    while input:

        # find entries without dependencies and add to output
        output.append([i for (i, j) in input if len(j) == 0])

        # reduce input by deleting all elements without dependencies and removing dependencies
        former_dependencies = set(output[-1])
        input = [(i, j - former_dependencies) for (i, j) in input if len(j) > 0]

    return output

input = [[1, []], [2, []], [3, set([2])], [4, set([2])], [5, set([3, 4])], [6, set([3, 4])]]
print(order_by_dependency(input))

并且输出符合预期:

  

[[1,2],[3,4],[5,6]]