Hvis du vil generere en ny liste fra en liste (array), hvis elementer er strenge, ved kun at udtrække de elementer af strenge, der opfylder visse betingelser, eller ved at udføre substitutioner, konverteringer osv., skal du bruge list comprehensions.
Efter en kort forklaring af list comprehensions forklares det følgende indhold med kodeeksempler.
- Udtrækning baseret på, om en bestemt streng er inkluderet eller ej (delvis match)
- Udskift en bestemt streng
- Udtræk ved at starte eller ikke starte med en bestemt streng
- Udtrække ved at slutte eller ikke slutte med en bestemt streng
- Vurderet og udtaget efter sag
- Konverter store og små bogstaver
- Bestemmer, om der anvendes alfabetiske eller numeriske tegn, og udtrækker dem
- Flere betingelser
- (computer) regulært udtryk
Bemærk, at lister kan lagre forskellige typer data og er helt forskellige fra arrays. Hvis du ønsker at håndtere arrays i processer, der kræver hukommelsesstørrelse og hukommelsesadresser eller numerisk behandling af store data, skal du bruge array (standardbiblioteket) eller NumPy.
- notation for optagelse i en liste
- Indeholder en bestemt streng (delvis match) \ Indeholder ikke: in
- Udskift en bestemt streng
- Begynder med en bestemt streng \ starter ikke: startswith()
- Afsluttes med en bestemt tegnstreng \ ikke afsluttes: endswith()
- Vurderet og udtaget efter sag
- Konverter store og små bogstaver
- Bestemmer, om der anvendes alfabetiske eller numeriske tegn, og udtrækker dem
- Flere betingelser
- (computer) regulært udtryk
notation for optagelse i en liste
Når der skal genereres en ny liste fra en liste, er list comprehensions enklere at skrive end for-loops.
[expression for any variable name in iterable object if conditional expression]
Hvis elementet kun skal vælges ved hjælp af et betinget udtryk, behandles det ikke ved hjælp af et udtryk, så det har følgende form
[variable name for variable name in original list if conditional expression]
Hvis det betingede if-udtryk omdannes til et betinget if-not-udtryk, bliver det til en negation, og elementer, der ikke opfylder det betingede udtryk, kan udtrækkes.
Indeholder en bestemt streng (delvis match) \ Indeholder ikke: in
I “specifik streng i original streng” returnerer True, hvis den originale streng indeholder den specifikke streng. Dette er et betinget udtryk.
Negationen af in sker med not in.
l = ['oneXXXaaa', 'twoXXXbbb', 'three999aaa', '000111222']
l_in = [s for s in l if 'XXX' in s]
print(l_in)
# ['oneXXXaaa', 'twoXXXbbb']
l_in_not = [s for s in l if 'XXX' not in s]
print(l_in_not)
# ['three999aaa', '000111222']
Udskift en bestemt streng
Hvis du ønsker at erstatte en streng af listeelementer, skal du bruge strengmetoden replace() for hvert element i listeforståelsesnotationen.
Hvis der ikke er nogen streng, der skal erstattes, er det ikke nødvendigt at vælge elementet i det betingede if-udtryk, da det ikke vil blive ændret ved at anvende replace().
l_replace = [s.replace('XXX', 'ZZZ') for s in l]
print(l_replace)
# ['oneZZZaaa', 'twoZZZbbb', 'three999aaa', '000111222']
Hvis du vil erstatte et helt element, der indeholder en bestemt streng, skal du udtrække det med in og behandle det med den ternære operatør. Den ternære operatør skrives i følgende form.True Value if Conditional Expression else False Value
Det er OK, hvis udtryksdelen af listeforståelsesnotationen er en ternær operatør.
l_replace_all = ['ZZZ' if 'XXX' in s else s for s in l]
print(l_replace_all)
# ['ZZZ', 'ZZZ', 'three999aaa', '000111222']
Nedenfor følger et resumé af resultaterne i parentes. Hvis du ikke er vant til at bruge parenteser, er det måske lettere at forstå og undgå fejl. Grammatisk set er der ikke noget problem, selv om du skriver parenteser.
[('ZZZ' if ('XXX' in s) else s) for s in l]
Brugen af in som en betingelse er forvirrende i forbindelse med listeforståelsesnotationen in, men det er ikke svært, hvis du kender den syntaktiske form for listeforståelsesnotationen og de ternære operatorer.
Begynder med en bestemt streng \ starter ikke: startswith()
Strengmetoden startswith() returnerer sandt, hvis strengen begynder med den streng, der er angivet i argumentet.
l_start = [s for s in l if s.startswith('t')]
print(l_start)
# ['twoXXXbbb', 'three999aaa']
l_start_not = [s for s in l if not s.startswith('t')]
print(l_start_not)
# ['oneXXXaaa', '000111222']
Afsluttes med en bestemt tegnstreng \ ikke afsluttes: endswith()
Strengmetoden endswith() returnerer sandt, hvis strengen slutter med den streng, der er angivet i argumentet.
l_end = [s for s in l if s.endswith('aaa')]
print(l_end)
# ['oneXXXaaa', 'three999aaa']
l_end_not = [s for s in l if not s.endswith('aaa')]
print(l_end_not)
# ['twoXXXbbb', '000111222']
Vurderet og udtaget efter sag
Strengmetoderne isupper(),islower() kan bruges til at bestemme, om en streng er med store eller små bogstaver.
l_lower = [s for s in l if s.islower()]
print(l_lower)
# ['three999aaa']
Konverter store og små bogstaver
Hvis du vil konvertere alle tegn til store eller små bogstaver, skal du bruge stringmetoderne upper() og lower(). Andre metoder omfatter capitalize(), som kun sætter det første bogstav med stort, og swapcase(), som bytter store og små bogstaver.
Som i substitutionseksemplet ovenfor skal du bruge den ternære operatør, hvis du kun vil behandle de elementer, der opfylder betingelsen.
l_upper_all = [s.upper() for s in l]
print(l_upper_all)
# ['ONEXXXAAA', 'TWOXXXBBB', 'THREE999AAA', '000111222']
l_lower_to_upper = [s.upper() if s.islower() else s for s in l]
print(l_lower_to_upper)
# ['oneXXXaaa', 'twoXXXbbb', 'THREE999AAA', '000111222']
Bestemmer, om der anvendes alfabetiske eller numeriske tegn, og udtrækker dem
Strengmetoderne isalpha() og isnumeric() kan bruges til at bestemme, om en streng er alfabetisk, numerisk osv.
l_isalpha = [s for s in l if s.isalpha()]
print(l_isalpha)
# ['oneXXXaaa', 'twoXXXbbb']
l_isnumeric = [s for s in l if s.isnumeric()]
print(l_isnumeric)
# ['000111222']
Flere betingelser
Den betingede udtryksdel i listeforståelser kan være flere betingelser. Negative “not”-betingelser kan også anvendes.
Når du bruger tre eller flere betingede udtryk, er det sikrere at omslutte hver gruppe med parenteser (), da resultatet vil variere afhængigt af rækkefølgen.
l_multi = [s for s in l if s.isalpha() and not s.startswith('t')]
print(l_multi)
# ['oneXXXaaa']
l_multi_or = [s for s in l if (s.isalpha() and not s.startswith('t')) or ('bbb' in s)]
print(l_multi_or)
# ['oneXXXaaa', 'twoXXXbbb']
(computer) regulært udtryk
Regelmæssige udtryk giver mulighed for meget fleksibel behandling.
Det matchobjekt, der returneres af re.match(), når det matcher, bestemmes altid til at være sandt, når det evalueres med et betinget udtryk. Hvis det ikke matcher, returneres None, som er falsk i det betingede udtryk. Så hvis du kun vil udtrække de elementer, der matcher det regulære udtryk, skal du blot anvende re.match() på den betingede udtryksdel af listeforståelsesudtrykket som før.
import re
l = ['oneXXXaaa', 'twoXXXbbb', 'three999aaa', '000111222']
l_re_match = [s for s in l if re.match('.*XXX.*', s)]
print(l_re_match)
# ['oneXXXaaa', 'twoXXXbbb']
re.sub(), som erstatter den matchede del af et regulært udtryk, er også nyttig. Hvis du kun vil udtrække og erstatte de matchede elementer, skal du blot tilføje “if conditional expression”.
l_re_sub_all = [re.sub('(.*)XXX(.*)', r'\2---\1', s) for s in l]
print(l_re_sub_all)
# ['aaa---one', 'bbb---two', 'three999aaa', '000111222']
l_re_sub = [re.sub('(.*)XXX(.*)', r'\2---\1', s) for s in l if re.match('.*XXX.*', s)]
print(l_re_sub)
# ['aaa---one', 'bbb---two']