web-dev-qa-db-fra.com

si / sinon dans une liste de compréhension?

Comment puis-je effectuer les opérations suivantes en Python?

row = [unicode(x.strip()) for x in row if x is not None else '']

Essentiellement:

  1. remplacez tous les Nones par des chaînes vides, puis
  2. effectuer une fonction.
729
AP257

Vous pouvez totalement le faire, c'est juste un problème de commande:

[unicode(x.strip()) if x is not None else '' for x in row]

En général,

[f(x) if condition else g(x) for x in sequence]

Et, pour les compréhensions de liste avec if conditions seulement,

[f(x) for x in sequence if condition]

Notez que cela utilise en fait une construction de langage différente, une expression conditionnelle , qui elle-même ne fait pas partie de la syntaxe de compréhension , tandis que la if après la for…in fait partie de la compréhension de liste et est utilisé pour filtrer des éléments de la source itérable.


Les expressions conditionnelles peuvent être utilisées dans toutes sortes de situations où vous souhaitez choisir entre deux valeurs d'expression basées sur une condition. Cela fait la même chose que opérateur ternaire ?: qui existe dans d'autres langues . Par exemple:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')
1106
poke

Une manière:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]

Bien que vous ayez alors:

row = map(change, row)

Ou vous pouvez utiliser un lambda inline.

40
Adam Vandenberg

Voici un autre exemple illustratif:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")
Ha, ha, ha!

Il exploite le fait que if i donne False pour 0 et à True pour toutes les autres valeurs générées par la fonction range(). Par conséquent, la compréhension de la liste est évaluée comme suit:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']
37
Bengt

Le problème spécifique ayant déjà été résolu dans les réponses précédentes, je vais donc aborder l'idée générale d'utiliser des conditionnels dans la compréhension de liste.

Voici un exemple qui montre comment les conditions conditionnelles peuvent être écrites dans une compréhension de liste:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

Notez que dans la compréhension de la première liste pour X_non_str, la commande est la suivante:

expression pour élément dans itérable si condition

et dans la dernière liste de compréhension pour X_str_changed, la commande est la suivante:

expression1 if condition else expression2 pour élément en itérable

J'ai toujours du mal à me souvenir que expresseion1 doit être avant si et expression2 doit être après else. Ma tête veut que les deux soient soit avant, soit après.

Je suppose que c'est conçu comme ça parce qu'il ressemble au langage normal, par exemple. "Je veux rester à l'intérieur si il pleut, sinon je veux aller à l'extérieur"

27
Tim Skov Jacobsen

Les autres solutions conviennent parfaitement à une seule construction if/else. Cependant, les déclarations ternaires au sein des listes de compréhension sont sans doute difficiles à lire.

L'utilisation d'une fonction facilite la lisibilité, mais une telle solution est difficile à étendre ou à adapter dans un flux de travail où le mappage est une entrée. Un dictionnaire peut atténuer ces préoccupations:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']
4
jpp

"Faire une liste d'éléments dans un itérable"

Il semble préférable de commencer par généraliser toutes les formes possibles plutôt que de donner des réponses spécifiques à des questions. Sinon, le lecteur ne saura pas comment la réponse a été déterminée. Voici quelques formulaires généralisés auxquels j'ai pensé avant de me donner mal à la tête, en essayant de décider si une clause finale else pourrait être utilisée dans le dernier formulaire.

[expression1 (item) pour item dans iterable]

[expression1 (item) si conditionnel1 pour item dans iterable]

[expression1 (item) si conditionnel1 sinon expression2 (item) pour item dans iterable]

[expression1 (item) si conditionnel1 sinon expression2 (article) pour item dans iterable si conditionnel2]

La valeur de 'item' ne doit être utilisée dans aucune des clauses conditionnelles. Une 'condition3' peut être utilisée comme commutateur pour ajouter ou non une valeur à la liste de sortie.

Par exemple, pour créer une nouvelle liste qui élimine les chaînes vides ou les chaînes d'espaces de la liste de chaînes d'origine:

newlist = [s pour s dans la première liste si s.strip ()]

0
Hewey Dewey

pas besoin de ternaire si/alors/sinon. à mon avis, votre question appelle cette réponse:

row = [unicode((x or '').strip()) for x in row]
0
mariotomo