Ved hjelp av 'in' å matche en egenskap av Python gjenstander i en matrise

stemmer
42

Jeg husker ikke om jeg drømte eller ikke, men jeg synes å huske at det er en funksjon som tillot noe sånt,

foo in iter_attr(array of python objects, attribute name)

Jeg har sett over docs, men denne type ting ikke faller inn under noen åpenbare børsnoterte overskrifter

Publisert på 03/08/2008 klokken 13:19
kilden bruker
På andre språk...                            


8 svar

stemmer
40

Ved hjelp av en liste forståelse ville bygge en midlertidig liste, som kunne spise alt minnet om sekvensen som søkte er stor. Selv om sekvensen er ikke stor, og bygge listen betyr itera over hele sekvensen før inkunne begynne sitt søk.

Den midlertidige listen kan være å unngå ved å anvende en generator uttrykk:

foo = 12
foo in (obj.id for obj in bar)

Nå, så lenge obj.id == 12nær begynnelsen av bar, vil søket være rask, selv om barer uendelig lang.

Som @Matt foreslått, er det en god ide å bruke hasattrhvis noen av objektene i barkan være mangler en idattributt:

foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
Svarte 11/09/2008 kl. 22:42
kilden bruker

stemmer
12

Er du ute etter å få en liste over objekter som har en viss egenskap? I så fall en liste forståelse er den riktige måten å gjøre dette.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
Svarte 03/08/2008 kl. 15:59
kilden bruker

stemmer
10

du kan alltid skrive en selv:

def iterattr(iterator, attributename):
    for obj in iterator:
        yield getattr(obj, attributename)

vil jobbe med noe som gjentar, det være seg en tuppel, en liste eller hva som helst.

Jeg elsker python, det gjør ting som dette veldig enkelt og ikke mer en problemfri enn nødvendig, og i bruk ting som dette er enormt elegant.

Svarte 27/08/2008 kl. 20:13
kilden bruker

stemmer
7

Nei, du var ikke drømme. Python har en ganske god liste forståelse system som lar deg manipulere listene ganske elegant, og avhengig av hva du ønsker å oppnå, kan dette gjøres et par måter. I hovedsak, hva du gjør er å si "For element i listen hvis criteria.matches", og fra det du kan bare iterere gjennom resultatene eller dumpe resultatene inn i en ny liste.

Jeg kommer til å crib et eksempel fra Dive Into Python her, fordi det er ganske elegant og de er smartere enn meg. Her er de få en liste over filer i en katalog, og deretter filtrere listen for alle filer som samsvarer med et regulært uttrykk kriterier.

    files = os.listdir(path)                               
    test = re.compile("test\.py$", re.IGNORECASE)          
    files = [f for f in files if test.search(f)]

Du kan gjøre dette uten regulære uttrykk, for eksempel, for noe der uttrykket på slutten returnerer true for en kamp. Det finnes andre alternativer som å bruke filteret () -funksjonen, men hvis jeg skulle velge, ville jeg gå med dette.

Eric Sipple

Svarte 03/08/2008 kl. 14:30
kilden bruker

stemmer
6

Funksjonen du tenker på er nok operator.attrgettter. For eksempel, for å få en liste som inneholder verdien av hvert objekt er "id" attributt:

import operator
ids = map(operator.attrgetter("id"), bar)

Hvis du ønsker å sjekke om listen inneholder et objekt med en id == 12, deretter en ryddig og effektiv (dvs. ikke gjenta hele listen unødvendig) måte å gjøre det på er:

any(obj.id == 12 for obj in bar)

Hvis du ønsker å bruke 'i' med attrgetter, og samtidig beholde lat gjentakelse av listen:

import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)

Svarte 05/02/2011 kl. 08:10
kilden bruker

stemmer
5

Hva jeg tenkte på kan oppnås ved hjelp av liste oppfattelser, men jeg tenkte at det var en funksjon som gjorde dette i en litt penere måte.

dvs. 'bar' er en liste over objekter, som alle har attributtet 'id'

Den mytiske funksjonell måte:

foo = 12
foo in iter_attr(bar, 'id')

Listen forståelse måte:

foo = 12
foo in [obj.id for obj in bar]

I ettertid listen forståelse måten er ganske ryddig allikevel.

Svarte 03/08/2008 kl. 16:13
kilden bruker

stemmer
3

Hvis du har planer om å søke noe av eksternt anstendig størrelse, er det beste alternativet vil være å bruke en ordbok eller et sett. Ellers, du i utgangspunktet har til å iterere gjennom hvert element i iterator til du kommer til den du ønsker.

Hvis dette ikke nødvendigvis ytelsessensitive kode, vil lista forståelse måten skal fungere. Men merk at det er ganske ineffektivt fordi det går over alle deler av iterator og deretter går tilbake over det igjen før den finner det den vil ha.

Husk, har python en av de mest effektive hashing algoritmer rundt. Bruke det til din fordel.

Svarte 27/08/2008 kl. 20:30
kilden bruker

stemmer
0

Jeg tror:

#!/bin/python
bar in dict(Foo)

Er det du tenker på. Når jeg prøver å se om en bestemt nøkkel eksisterer i en ordbok i python (python versjon av en hash tabell) er det to måter å sjekke. Først er den has_key()metode festet til ordbok og andre er det eksemplet som er gitt ovenfor. Det vil returnere en boolsk verdi.

Det burde svare på spørsmålet ditt.

Og nå litt off topic å knytte dette til liste forståelse svaret tidligere gitt (for litt mer klarhet). Liste oppfattelser konstruere en liste fra en grunnleggende for løkke med modifiseringsmidler. Som et eksempel (for å klargjøre svakt), en måte å bruke in dictspråkkonstrukt i en liste forståelse :

Si du har en todimensjonal ordbok foo, og du bare vil at andre dimensjonen ordbøker som inneholder nøkkelen bar. En relativt enkel måte å gjøre det ville være å bruke en liste forståelse med en betinget som følger:

#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])

Legg merke til if bar in valuepå slutten av setningen **, er dette et modifiserende klausul som forteller liste forståelse for å bare holde disse nøkkelverdi-par som tilfredsstiller den betingede. ** I dette tilfellet bazer en ny ordbok som inneholder bare ordbøker fra foo som inneholder bar (Forhåpentligvis jeg ikke glipp av noe i denne koden eksempel ... du kanskje ta en titt på listen forståelse dokumentasjon finnes i docs.python.org tutorials og secnetix.de , begge områdene er gode referanser hvis har du spørsmål i fremtiden.).

Svarte 03/08/2008 kl. 15:47
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more