(“解压缩”显然是一个不好的名字,但我不确定哪个才是正确的。如果这意味着我由于不知道要搜索什么而错过了权威答案,请原谅。)
假设我们有
people = [
(1, 'anne'),
(2, 'ben'),
(3, 'charlie'),
]( django中常见的选项等)
现在我们需要一个“键”列表或第一个元素的列表:[1, 2, 3]
在python 3中,我使用
people_ids, _ = list(zip(*people))
# or even
people_ids = [p[0] for p in people]zip的方式看起来并不是很整洁,特别是Python3需要额外的list(...)来使zip成为迭代器。
第二种理解方法更具可读性,但不能一概而论,例如。在同一次调用中返回第二个、第三个元素等的列表。
有没有更好的方法?
(其中“更好”主要是指干净和可读,但性能也可能有一些可观的)
发布于 2016-04-08 17:58:03
使用next,您可以从迭代器中获取第一项:
>>> people = [
... (1, 'anne'),
... (2, 'ben'),
... (3, 'charlie'),
... ]
>>> next(zip(*people))
(1, 2, 3)对operator.itemgetter使用map的替代方案
>>> import operator
>>> list(map(operator.itemgetter(0), people))
[1, 2, 3]顺便说一句,没有list的zip解决方案应该可以工作:
>>> people_ids, _ = zip(*people)
>>> people_ids
(1, 2, 3)发布于 2016-04-08 18:09:02
对于特定的示例,您可以稍微“滥用”一下dict
people = [
(1, 'anne'),
(2, 'ben'),
(3, 'charlie'),
]
d_people = dict(people)然后你就有了一个很好的数据模型。这有一些问题:键不能重复,并且不能处理具有两个以上元素的元组。但是对于这种情况(这是非常典型的!)效果非常好。
然后,您可以通过执行keys命令来简单地获取密钥
d_people.keys()或者,显式列表:
list(d_people)
list(d_people.keys())它们是等价的。
发布于 2016-04-08 18:12:35
获取基于ids的子集可以由operator.itemgetter完成。可以通过创建显式切片对象并将其传递给函数来获得压缩后的值的子切片。
import operator
people = [
(1, 'anne', 'some'),
(2, 'ben', 'another'),
(3, 'charlie', 'field'),
]
people_ids = [p[0] for p in people] # 0 may be passed as funtion argument
people_ids_and_another = [operator.itemgetter(*[0, 2])(p) for p in people] # [0, 2] may be passed as function argument
people_ids_and_name_via_slice = [p[slice(0,2,None)] for p in people] # equal to p[0:2], but passable as argument要演示函数用法,请执行以下操作:
def dezip(seq, what):
if isinstance(what, list):
return [operator.itemgetter(*what)(p) for p in people]
else:
return [p[what] for p in people]
assert dezip(people, slice(0,2,None)) == [(1, 'anne'), (2, 'ben'), (3, 'charlie')]
assert dezip(people, 0) == [1, 2, 3]
assert dezip(people, [0, 2]) == [(1, 'some'), (2, 'another'), (3, 'field')]如果你要去掉'list of in‘的要求,你可以去掉函数体中的If语句。
https://stackoverflow.com/questions/36496439
复制相似问题