通过属性选择特征(如果在Python列表中)?


14

我正在尝试在Python中根据属性是否存在于列表中的查询来完成按属性选择。

最简单的查询应该是这样的:

qry = " \"OBJECTID\" in oid_list"
arcpy.SelectLayersByAttribute_management(inft, "NEW_SELECTION", qry)

但是该方法返回无效的表达式错误。

过去,对于这种类型的查询,我不得不使用更复杂的语法,例如:

sqlQuery2 = "nid in (" + ','.join(["'"+x+"'" for x in delta_list]) +")"

但是改编此代码段似乎对我也不起作用,即:

 "OBJECTID_1 in (" + ','.join(["'"+str(x)+"'" for x in oid_list]) +")"

我在这里想念什么?

Answers:


16

您的原始查询可能已修改为整数列表:

'"OBJECTID_1" IN ' + str(tuple(oid_list))

因此,如果为oid_list = [7, 9, 4, 8],则结果为:

"OBJECTID_1" IN (7, 9, 4, 8)

请注意,如果oid_list始终有两个或多个项目,则此“技巧”将起作用,因为其他有效的元组(例如()(7,))将导致SQL语法错误。

一个也可以处理零个或一个oid_list项目的通用表达式是:

'"OBJECTID_1" IN ({0})'.format(', '.join(map(str, oid_list)) or 'NULL')

我没有意识到ArcGIS选择界面支持的“ IN”。这可能比我的解决方案更有效。
AHigh

1
请注意,IN查询支持一个上限,我认为它是2000条记录
Tristan Forward

9

这是此答案中函数的略微修改版本,可以接受Python列表而不是用分号分隔的字符串:

def buildWhereClauseFromList(table, field, valueList):
    """Takes a list of values and constructs a SQL WHERE
    clause to select those values within a given field and table."""

    # Add DBMS-specific field delimiters
    fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(table).path, field)

    # Determine field type
    fieldType = arcpy.ListFields(table, field)[0].type

    # Add single-quotes for string field values
    if str(fieldType) == 'String':
        valueList = ["'%s'" % value for value in valueList]

    # Format WHERE clause in the form of an IN statement
    whereClause = "%s IN(%s)" % (fieldDelimited, ', '.join(map(str, valueList)))
    return whereClause

6

我认为最直接的方法是迭代列表中的值,并将它们添加到选择中(这样您就可以使用列表中的每个值更改查询)。像这样:

oidList = [1,2,3,4]
arcpy.management.MakeFeatureLayer(thisFC,thisLyr)
for values in oidList:
    query = "\"OBJECTID\"="+str(values)
    arcpy.management.SelectLayerByAttribute(thisLyr,"ADD_TO_SELECTION",query)

即使没有选择任何功能,也可以使用ADD_TO_SELECTION,它将在第一次迭代时创建一个新选择。

编辑:

如果您认为执行单个SelectLayerByAttribute的成本太高,则可以使用这种方法,根据列表长度创建一个很大的选择子句:

oidList = [1,2,3,4]
arcpy.management.MakeFeatureLayer(thisFC,thisLyr)
query=""
q=""
oidList.sort()
for x in oidList:
    query="\"OBJECTID\"="+str(x)+" OR "+q
    q=query
q=q[1:-4]
arcpy.management.SelectLayerByAttribute(thisLyr,"NEW_SELECTION",q)

有趣的想法是遍历值并为每次迭代执行一次select by属性。我将对此进行测试,但我相当确定这应该可行。谢谢。
jsnider 2012年

这似乎是可行的,但肯定会需要一些时间来处理每个单独的选择,以获得更长的列表。
jsnider 2012年

2
用其他方法更新了答案。
AHigh

更新答案的好主意。我选择使用此方法,因为它可以更快地处理较大的列表。稍作修改:q =“”对于oid_set中的x:query ='“ OBJECTID_1” ='+ str(x)+'OR'q =查询q = q [1:-4],然后选择属性。似乎可以工作!
jsnider

我将使用您选择的方法来更新答案,以便对其进行解析并使其更易于阅读。很高兴它起作用。
AHigh 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.