Pesquisar se o campo existe na classe de recurso

8

Tenho algumas dezenas de classes de recursos, uma das quais contém o campo que estou procurando. Eles são armazenados em vários bancos de dados geográficos de arquivos diferentes.

Existe uma maneira rápida de pesquisar cada classe de recurso para encontrar a que possui meu campo? Ou tenho que verificar a tabela de atributos de cada um no Catálogo? Alguns dos arquivos têm o mesmo nome, mas são armazenados em locais separados.

Gostaria de poder fazer isso dentro de uma Calculate Valueferramenta no ModelBuilder, para que, sempre que necessário, pudesse executar o modelo em um único arquivo gdb e ele pesquisasse todas as classes de recursos desse gdb e procurasse o campo .

Até agora, eu tenho um iterador de classe de recurso que itera sobre todas as classes de recurso no arquivo gdb recursivamente. Dentro do Calculate Valueeu tenho o seguinte código:

findField(r"%Feature%", "%Search Field%")

def findField(fc, fi):
  lst = arcpy.ListFields(fc)
  for f in lst:
    if f.name == fi:
      return fc
    else:
      return "not found"

Os valores retornados são coletados em Output Valuescomo seqüências de caracteres. A saída para todas as classes de recursos foi "não encontrada", mesmo que o campo exista em pelo menos 4 delas. insira a descrição da imagem aqui

Cindy Jayakumar
fonte
Do que você está tentando calcular o valor? Você está tentando inserir registros em uma tabela? Não faz muito sentido o que você está tentando usar a ferramenta Calculate Value for ...
RyanKDalton
Coloquei o código Python dentro do Calculate Valuepara pesquisar o campo e retornar o caminho da classe feature como uma string, se encontrar o campo - veja minha resposta abaixo.
Cindy Jayakumar

Respostas:

4

Eu preferiria uma compreensão da lista em vez de operações de string (como resposta aceita). Na minha opinião, isso é mais legível e pitônico. Além disso, a abordagem de compreensão da lista pode ser estendida adicionando mais funcionalidades ( str.lower()como o @RyanDalton) muito fácil.

def findField(fc, fi):
  fieldnames = [field.name for field in arcpy.ListFields(fc)]
  if fi in fieldnames:
    return "found in " +fc
  else:
    return "not found in " +fc

Se você preferir a instrução if-else de um forro:

def findField(fc, fi):
  fieldnames = [field.name for field in arcpy.ListFields(fc)]
  return "found in " + fc if fi in fieldnames else "not found in " + fc

Ou ainda mais curto, mas menos legível:

    def findField(fc, fi):
      return "found in " + fc if fi in [field.name for field in arcpy.ListFields(fc)] else "not found in " + fc
Saleika
fonte
Sim, essa seria a resposta preferida agora. Eu fiz essa pergunta há muito tempo, me custa lembrar os 9 meses que perdi no ModelBuilder antes de mudar totalmente para o Python, em vez de cortar pedaços.
Cindy Jayakumar
19

Confira esta função de Bjorn Kuiper para testar se existe um campo :

def FieldExist(featureclass, fieldname):
    fieldList = arcpy.ListFields(featureclass, fieldname)

    fieldCount = len(fieldList)

    if (fieldCount == 1):
        return True
    else:
        return False

com o seguinte exemplo de uso:

    if (not FieldExist(myFeatureClass, "myField")):
      arcpy.AddError("Field 'myField' does not exist in " + myFeatureClass)
      sys.exit()
Dana
fonte
Acabei usando algo semelhante há algum tempo, mas não deu exatamente a saída que estava procurando.
Cindy Jayakumar
12

você pode usar arcpy:

import arcpy

myField = "test"

env.workspace = "D:/test/data.gdb"
fcs = arcpy.ListFeatureClasses()

for f in fcs:
    fieldList = arcpy.ListFields(f)
    for field in fieldList:   
         if field.name == myField:
             print f

Além disso, você pode usar o os.walk para arquivos em sua unidade como:

path = r"C:"
for root, dirs, files in os.walk(path):
    for fileName in files:
            .........

espero que ajude você ....

Aragão
fonte
Eu tentei e, embora o código faça sentido, ele não faz nada. Eu testei usando um campo que está em quatro das minhas classes de recursos - o script foi executado, mas não produziu nada.
Cindy Jayakumar
oh desculpe, esqueci de repetir os campos no fieldset, agora atualizo minha resposta e testei-a.
Aragão
Eu tentei com o código atualizado, ele é executado, mas não gera saída, embora o campo esteja em várias classes de recursos no geodatabase.
Cindy Jayakumar
3

Arabella, são as suas façanhas em conjuntos de dados de recursos? Nesse caso, a solução do @ Aragon não funcionará porque você precisa percorrer os conjuntos de dados dos recursos e verificar as classes de recursos.

Usando o código de @ Aragon e o de @ gotchula de Listar todas as classes de recursos no GDB, inclusive nos conjuntos de dados de recursos , eu produzi o código a seguir que lerá todos os conjuntos de dados de recursos e classes de recurso em um geodatabase.

NOTA : Por padrão, ListFields parece fazer distinção entre maiúsculas e minúsculas. Adicionei código para converter o nome do campo definido pelo usuário e o nome do ListField em minúsculas para pesquisas que não diferenciam maiúsculas de minúsculas. Você provavelmente também desejaria desativar a maioria das instruções de impressão, mas as deixei lá para que você possa seguir o código enquanto ele está sendo executado. Eu também criei a subfunção FindField dentro do arquivo para que eu pudesse chamá-lo várias vezes no script sem precisar codificá-lo novamente.

import arcpy

def FindField(fc,myField):
    fieldList = arcpy.ListFields(fc)
    for field in fieldList:
        if str.lower(str(field.name)) == str.lower(myField):
            print "    " + fc + " contains fieldname: " + myField

myField = "test"
arcpy.env.workspace = "D:/test/data.gdb"

#Search root level featureclasses
for fc in arcpy.ListFeatureClasses():
    print "Searching root level Featureclasses..."
    print "  Searching " + fc
    FindField(fc,myField)

#Search Feature Datasets
for fds in arcpy.ListDatasets('','feature'):
    print "Searching FeatureDataset: " + fds

    for fc in arcpy.ListFeatureClasses('','',fds):
        print "  Searching Featureclass... " + fc
        FindField(fc,myField)
RyanKDalton
fonte
Eu estaria executando isso em um modelo, então eu o adaptei um pouco e testei. Não tenho certeza do que quero Calculate Valueque retorne - posso return "true" if FindField(fc,myField) =="true" else "false"?
Cindy Jayakumar
Ah, acabei de perceber que meu comentário anterior não me dizia nada. Também executar esse teste booleano dentro do modelo não retorna nada.
Cindy Jayakumar
Calcluir valor? Teste booleano? Eu acho que você deveria esclarecer sua pergunta sobre o que exatamente você procura.
precisa saber é o seguinte
Eu editei a pergunta.
Cindy Jayakumar
2

Alguns dançaram da maneira que eu faria isso, mas eu só quero adicionar uma maneira fácil de fazer uma linha:

if 'fieldname' in [f.name for f in arcpy.ListFields(fc)]:
    ## do something.

O que talvez seja mais útil (se você estiver repetindo várias classes de recursos), usaria o oposto do acima como filtro:

for fc in arcpy.ListFeatureClasses():
    if not 'fieldname' in [f.name for f in arcpy.ListFields(fc)]:
        continue
    ## now do something with the feature class.
mr.adam
fonte
1

Encontre a resposta com alguma ajuda do código na resposta a esta pergunta . Peguei todos os nomes de campos, os converti em uma sequência e depois procurei na sequência pelo meu campo. O código Calculate Valueagora é o seguinte:

def findField(fc, fi):
  fieldList = arcpy.ListFields(fc)
  nameList = []
  for f in fieldList:
    nameList.append(f.name)
  str_lst = "!" + "!, !".join(nameList) + "!"
  return "found in" +fc if str_lst.find(fi) > 0 else "not found in " +fc

O Output Valuesagora contém a lista completa de classes de recursos que possuem o campo que eu procurei e not foundo restante.

Saída Coletar Valores

Cindy Jayakumar
fonte