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


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

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()

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ê ....


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)

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.

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.