J'ai une liste de tuples
servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
Je veux créer une nouvelle liste qui n'a que les deux premiers champs comme dans:
[('server1', 80), ('server2', 443)]
mais je ne vois pas comment créer une compréhension de liste pour plus d'un élément.
hosts = [x[0] for x in servers] # this works to give me ['server1', server2']
hostswithports = [x[0], x[1] for x in servers] # this does not work
Je préfère apprendre la méthode Pythonic vs utiliser une boucle - qu'est-ce que je fais mal?
Vous pouvez utiliser déballage itératif étend .
>>> servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
>>> [(server, port) for server, port, *_ in servers]
[('server1', 80), ('server2', 443)]
En utilisant _
comme nom d'espace réservé jetable est une convention courante.
Ce que vous faisiez était presque correct. Vous tentiez de traduire chaque tuple de votre liste en un nouveau tuple. Mais vous avez oublié de déclarer le tuple. Voilà ce que font les parenthèses:
hosts = [(x[0], x[1]) for x in servers]
Utiliser le découpage de base, qui a l'avantage de ne pas échouer si l'un des éléments de votre liste ne possède pas le nombre attendu de sous-éléments.
[el[:2] for el in servers]
[('server1', 80), ('server2', 443)]
Vous pouvez utiliser itemgetter :
from operator import itemgetter
servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
result = list(map(itemgetter(0, 1), servers))
print(result)
Sortie
[('server1', 80), ('server2', 443)]
Une alternative plus lisible est la suivante:
from operator import itemgetter
get_server_and_port = itemgetter(0, 1)
servers = [('server1', 80, 1, 2), ('server2', 443, 3, 4)]
result = [get_server_and_port(e) for e in servers]
print(result) # [('server1', 80), ('server2', 443)]