列表理解从元组列表中提取多个字段

Bil*_*ll 19 python tuples python-itertools

我有一个元组列表

servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
Run Code Online (Sandbox Code Playgroud)

我想创建一个只有前两个字段的新列表,如:

 [('server1', 80), ('server2', 443)]
Run Code Online (Sandbox Code Playgroud)

但我看不出如何为多个元素制作列表理解.

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
Run Code Online (Sandbox Code Playgroud)

我更喜欢学习使用循环的pythonic方式 - 我做错了什么?

tim*_*geb 38

您可以使用扩展的可迭代解包.

>>> servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]
>>> [(server, port) for server, port, *_ in servers]
[('server1', 80), ('server2', 443)]
Run Code Online (Sandbox Code Playgroud)

使用_作为一次性占位符名称是一种常见的约定.

  • 这是唯一一个只通过查看相关行,我知道发生了什么.可读性至关重要:+1 (3认同)
  • ...对于旧版本,`[服务器,端口)服务器,端口,_,_在服务器中``也可以. (2认同)

Woo*_*193 15

你在做什么几乎是正确的.您试图将列表中的每个元组转换为新元组.但你忘了实际宣布元组.这就是括号正在做的事情:

hosts = [(x[0], x[1]) for x in servers]
Run Code Online (Sandbox Code Playgroud)


use*_*203 15

使用基本切片,如果您的任何列表元素没有预期数量的子元素,则具有不失败的好处.

[el[:2] for el in servers]
Run Code Online (Sandbox Code Playgroud)

[('server1', 80), ('server2', 443)]
Run Code Online (Sandbox Code Playgroud)


Dan*_*ejo 7

你可以使用itemgetter:

from operator import itemgetter


servers = [('server1', 80 , 1, 2), ('server2', 443, 3, 4)]

result = list(map(itemgetter(0, 1), servers))

print(result)
Run Code Online (Sandbox Code Playgroud)

产量

[('server1', 80), ('server2', 443)]
Run Code Online (Sandbox Code Playgroud)

更具可读性的替代方案如下:

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)]
Run Code Online (Sandbox Code Playgroud)

  • 一个小的替代方法是将一个切片对象传递给itemgetter:`itemgetter(slice(n))`相当于`itemgetter(0,1,2,...,n-1)`,以防你想选择一个非平凡大小的指数范围.您可以使用2或3个参数调用切片构造函数,这些参数适用于分别跳过索引的第一个或多个元素之后的范围,例如下标切片表达式(`foo [start:stop:step]`). (2认同)