タプルのリストがあります
servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
次のように最初の2つのフィールドのみを持つ新しいリストを作成します。
[('server1', 80), ('server2', 443)]
しかし、複数の要素のリスト理解を作成する方法がわかりません。
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
ループを使用するよりもPythonicの方法を学ぶほうが好きです-何が間違っていますか?
extended iterable unpacking を使用できます。
>>> servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
>>> [(server, port) for server, port, *_ in servers]
[('server1', 80), ('server2', 443)]
_
を使い捨てのプレースホルダー名として使用することは一般的な規則です。
あなたがやっていたことはほぼ正しいことでした。リスト内の各タプルを新しいタプルに変換しようとしました。しかし、実際にタプルを宣言するのを忘れました。それが括弧がしていることです:
hosts = [(x[0], x[1]) for x in servers]
基本的なスライシングを使用します。これには、リスト要素のいずれかにサブ要素の予想数がない場合でも失敗しないという利点があります。
[el[:2] for el in servers]
[('server1', 80), ('server2', 443)]
itemgetter を使用できます。
from operator import itemgetter
servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
result = list(map(itemgetter(0, 1), servers))
print(result)
出力
[('server1', 80), ('server2', 443)]
より読みやすい代替手段は次のとおりです。
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)]