Python listesindeyken özellikleri özelliğe göre mi seçiyorsunuz?


14

Python özniteliğine göre bir seçim tamamlamak çalışıyorum ama bir öznitelik bir listede olup olmadığını sorgusuna göre.

Böyle bir sorgu en basit haliyle şöyle olmalıdır:

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

ancak bu yaklaşım geçersiz bir ifade hatası döndürür.

Geçmişte, bu tür bir sorgu için daha karmaşık sytax kullanmak zorunda kaldım, örneğin:

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

ancak bu snippet'in bir uyarlaması da benim için çalışmıyor gibi görünüyor, yani:

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

Burada ne eksik?

Yanıtlar:


16

Orijinal sorgunuz bir tamsayı listesi için değiştirilmiş olabilir:

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

eğer oid_list = [7, 9, 4, 8]öyleyse, sonuç:

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

Bu "hile" oid_listnin her zaman iki veya daha fazla öğe varsa işe yaradığını unutmayın , çünkü ()veya gibi diğer geçerli tuples'ler (7,)bir SQL sözdizimi hatasıyla sonuçlanacaktır.

Sıfır veya bir oid_listöğeyi de işleyecek daha genel bir ifade şöyle olacaktır:

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

'IN' destekli ArcGIS seçim arayüzünün farkında değildim. Bu muhtemelen benim çözümümden daha etkilidir.
ahigh

1
Sadece IN sorgusu tarafından desteklenen bir üst sınır var, ben 2000 kayıtları olduğunu düşünüyorum
Tristan Forward

9

Noktalı virgülle ayrılmış bir dize yerine bir Python listesini kabul etmek için bu yanıttaki işlevin biraz değiştirilmiş bir sürümü :

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

Bunun en basit yaklaşım, tek tek listenizdeki değerleri yinelemek ve seçim için onları eklemek olduğunu (Bu yüzden listedeki her bir değer ile sorgunuzu değiştirebilirsiniz) olduğunu düşünüyorum. Bunun gibi bir şey:

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)

Seçili özellik olmasa bile ADD_TO_SELECTION özelliğini kullanabilirsiniz, ilk yinelemede yeni bir seçim oluşturacaktır.

Düzenle:

Bireysel SelectLayerByAttribute yapmanın maliyetinin çok yüksek olacağını düşünüyorsanız, liste uzunluğunuza bağlı olarak oldukça büyük bir seçim cümlesi oluşturduğunuz gibi bir yaklaşım kullanabilirsiniz:

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)

Değerleri yinelemek ve her yineleme için bir özniteliğe göre seçim yapmak için ilginç bir fikir. Bunu test edeceğim, ama bunun işe yarayacağından oldukça eminim. Teşekkürler.
jsnider

bu çalışıyor gibi görünüyor, ancak her bir seçimi daha uzun listeler için işlemek için kesinlikle biraz zaman olacak.
jsnider

2
Cevabı farklı bir yaklaşımla güncelledi.
ahigh

Güncellenmiş cevap ile iyi fikir. Bu yaklaşımı daha büyük listeleri işlemek için çok daha hızlı olarak kullanmayı seçtim. Biraz değiştirildi: oid_set içindeki x için q = "": query = '"OBJECTID_1" =' + str (x) + 'VEYA' q = sorgu q = q [1: -4] ve ardından iki özellik seçin. Çalışıyor gibi görünüyor!
jsnider

Yanıtımı seçtiğiniz yaklaşımla güncelleyeceğim, böylece çözümlenecek ve okunması kolay olacak. Çalıştığına sevindim.
ahigh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.