Memilih fitur berdasarkan atribut jika dalam daftar Python?


14

Saya mencoba untuk menyelesaikan pilih dengan atribut dalam Python tetapi berdasarkan permintaan apakah atribut hadir dalam daftar.

Kueri seperti itu paling sederhana seharusnya berupa sesuatu seperti ini:

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

tetapi pendekatan itu mengembalikan kesalahan ekspresi yang tidak valid.

Di masa lalu, saya harus menggunakan sytax yang lebih rumit untuk jenis kueri ini, seperti:

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

tetapi adaptasi dari cuplikan ini juga tidak bekerja untuk saya, yaitu .:

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

Apa yang kulewatkan di sini?

Jawaban:


16

Kueri asli Anda dapat dimodifikasi untuk daftar bilangan bulat:

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

jadi jika oid_list = [7, 9, 4, 8], maka hasilnya adalah:

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

Ketahuilah bahwa "trik" ini berfungsi jika oid_listselalu memiliki dua item atau lebih, karena tupel valid lainnya, seperti ()atau (7,), akan menghasilkan kesalahan sintaks SQL.

Ekspresi yang lebih umum yang juga menangani nol atau satu oid_listitem adalah:

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

Saya tidak menyadari antarmuka pemilihan ArcGIS yang didukung 'IN'. Ini mungkin lebih efisien daripada solusi saya.
Hampir

1
Hanya berhati-hatilah ada batas atas yang didukung oleh permintaan IN Saya pikir ini 2000 catatan
Tristan Forward

9

Berikut adalah versi fungsi yang sedikit dimodifikasi dalam jawaban ini , untuk menerima daftar Python alih-alih string yang dipisah koma:

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

Saya pikir pendekatan yang paling mudah untuk ini adalah untuk mengulangi nilai-nilai dalam daftar Anda secara tunggal dan menambahkannya ke pilihan (Jadi, Anda dapat mengubah kueri Anda dengan setiap nilai dalam daftar). Sesuatu seperti ini:

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)

Anda dapat menggunakan ADD_TO_SELECTION bahkan jika tidak ada fitur yang dipilih, itu akan membuat pilihan baru pada iterasi pertama.

Edit:

Jika Anda berpikir biaya untuk melakukan SelectLayerByAttribute secara individual akan terlalu tinggi, Anda dapat menggunakan pendekatan seperti ini di mana Anda membuat klausa pilihan yang cukup besar tergantung pada panjang daftar Anda:

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)

Ide menarik untuk beralih melalui nilai-nilai dan melakukan pemilihan dengan atribut untuk setiap iterasi. Saya akan menguji ini, tapi saya cukup yakin ini akan berhasil. Terima kasih.
jsnider

ini kelihatannya bekerja, tetapi pasti akan ada waktu untuk memproses setiap seleksi individu untuk daftar yang lebih panjang.
jsnider

2
Memperbarui jawabannya dengan pendekatan berbeda.
Hampir

Ide bagus dengan jawaban yang diperbarui. Saya telah memilih untuk menggunakan pendekatan ini karena lebih cepat untuk memproses daftar yang lebih besar. Dimodifikasi sedikit: q = "" untuk x di oid_set: query = '"OBJECTID_1" =' + str (x) + 'OR' q = permintaan q = q [1: -4] lalu pilihbyattribusi. Tampaknya bekerja!
jsnider

Saya akan memperbarui jawaban saya dengan pendekatan yang Anda pilih sehingga diuraikan dan lebih mudah dibaca. Senang itu berhasil.
Hampir
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.