Pythonリストにある場合、属性によって機能を選択しますか?


13

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]) +")"

ここで何が欠けていますか?

回答:


15

元のクエリは、整数のリスト用に変更されている可能性があります。

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

の場合oid_list = [7, 9, 4, 8]、結果は次のようになります。

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

この「トリック」は、oid_list常に2つ以上のアイテムがある場合に機能することに注意してください。これは、()or などの他の有効なタプル(7,)によってSQL構文エラーが発生するためです。

0個または1個のoid_listアイテムも処理するより一般的な式は次のとおりです。

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

ArcGISの選択インターフェイスが「IN」をサポートしていることを知りませんでした。これはおそらく私のソリューションよりも効率的です。
AHigh

1
ただ、私はそれが2000年の記録だと思うのクエリでサポートされる上限があり警戒する
トリスタンフォワード

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)

値を反復処理し、各反復で属性による選択を実行する興味深いアイデア。これをテストしますが、これが機能するはずです。ありがとう。
jsnider

これは機能しているように見えますが、長いリストの個々の選択を処理する時間は確かにあります。
jsnider

2
別のアプローチで回答を更新しました。
AHigh

更新された答えをお勧めします。大きなリストを処理するためにはるかに高速であるため、このアプローチを使用することを選択しました。わずかに変更:q = "" for oid_set:query = '"OBJECTID_1" =' + str(x)+ 'OR' q = query q = q [1:-4]そして、selectbyattribute。動作しているようです!
jsnider

解析し読みやすくするために、選択したアプローチで回答を更新します。良かった。
AHigh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.