Wybieranie funkcji według atrybutu na liście Python?


14

Próbuję dokończyć wybór według atrybutu w Pythonie, ale na podstawie zapytania, czy atrybut jest obecny na liście.

Takie zapytanie w najprostszej formie powinno być takie:

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

ale to podejście zwraca nieprawidłowy błąd wyrażenia.

W przeszłości musiałem używać bardziej skomplikowanej sytax dla tego typu zapytań, takich jak:

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

ale adaptacja tego fragmentu też nie wydaje mi się działać, tj .:

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

Czego tu brakuje?

Odpowiedzi:


16

Twoje pierwotne zapytanie mogło zostać zmodyfikowane dla listy liczb całkowitych:

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

więc jeśli oid_list = [7, 9, 4, 8], to wynik jest następujący:

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

Należy pamiętać, że ta „sztuczka” działa, jeśli oid_listzawsze zawiera dwa lub więcej elementów, ponieważ inne prawidłowe krotki, takie jak ()lub (7,), spowodują błąd składni SQL.

Bardziej ogólne wyrażenie, które obsługiwałoby również zero lub jeden oid_listelement, to:

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

Nie zdawałem sobie sprawy, że interfejs wyboru ArcGIS obsługuje „IN”. Jest to prawdopodobnie bardziej wydajne niż moje rozwiązanie.
— AHigh

1
Uważaj, istnieje górna granica obsługiwana przez zapytanie IN. Myślę, że to 2000 rekordów
— Tristan Forward

9

Oto nieco zmodyfikowana wersja funkcji w tej odpowiedzi , aby zaakceptować listę Python zamiast łańcucha rozdzielanego średnikami:

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

Myślę, że najprostszym podejściem do tego jest iteracja pojedynczych wartości na liście i dodanie ich do zaznaczenia (aby można było zmienić zapytanie przy każdej wartości na liście). Coś takiego:

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)

Możesz użyć ADD_TO_SELECTION, nawet jeśli nie wybrano żadnych funkcji, utworzy nowy wybór przy pierwszej iteracji.

Edytować:

Jeśli uważasz, że koszt wykonania pojedynczego SelectLayerByAttribute będzie zbyt wysoki, możesz zastosować takie podejście, w którym tworzysz dość dużą klauzulę wyboru w zależności od długości listy:

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)

Ciekawy pomysł na iterację po wartościach i wykonanie wyboru według atrybutu dla każdej iteracji. Przetestuję to, ale jestem pewien, że to powinno zadziałać. Dzięki.
— jsnider

wydaje się, że to działa, ale na pewno zajmie trochę czasu przetworzenie każdej selekcji dla dłuższych list.
— jsnider

2
Zaktualizowałem odpowiedź, stosując inne podejście.
— AHigh,

Dobry pomysł ze zaktualizowaną odpowiedzią. Wybrałem to podejście, ponieważ jest ono znacznie szybsze do przetwarzania większych list. Nieznacznie zmodyfikowano: q = "" dla x w oid_set: query = '"OBJECTID_1" =' + str (x) + 'OR' q = zapytanie q = q [1: -4], a następnie wybierz by atrybut. Wydaje się działać!
— jsnider

Zaktualizuję moją odpowiedź z wybranym przez Ciebie podejściem, aby była przeanalizowana i łatwiejsza do odczytania. Cieszę się, że to zadziałało.
— AHigh
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.