用空集合作为初始值的reduce
我有一个列表,里面又包含了多个子列表,我想从这些子列表中提取出所有的元素,构建一个集合。
举个例子:a = [[1,2],[2,3]]
这个列表应该能得到 set([1,2,3])
,也就是一个包含1、2和3的集合。
我试过用 reduce(lambda x,y:x.update(y),a,set([]))
这个方法,但出现了一个错误,提示 AttributeError: 'NoneType'
对象没有 'update' 这个属性。
有没有人能告诉我怎么用 reduce 函数来实现这个功能呢?
6 个回答
2
Kindall已经回答了如何使用reduce()
来完成这个任务,但我觉得用itertools.chain.from_iterable()
的方法更简洁一些:
import itertools
a = [[1, 2], [2, 3]]
print set(itertools.chain.from_iterable(a))
16
根据要求:
>>> from functools import reduce
>>> a = [[1,2],[2,3]]
>>> reduce(lambda s, elems: s.union(elems), a, set())
set([1, 2, 3])
另外一种方法,纯粹是为了好玩:
>>> from itertools import chain
>>> set(chain.from_iterable(a))
set([1, 2, 3])
再来一种,纯粹是为了酷炫:
>>> set.union(set(), *a)
set([1, 2, 3])
9
问题在于,使用 update()
方法更新一个集合时,它会返回 None
,而不是更新后的集合。这是文档中说明的,也是预期的行为。如果你确实想用 update()
,你可以把你的 lambda 表达式写成这样:
lambda x, y: x.update(y) or x
这里的 or
语句会在第一个条件为“假”的时候返回 x
(而 None
就是“假”)。
不过,我觉得你其实应该用 union()
,而不是 update()
。它的功能基本相同,但会返回结果。
lambda x, y: x.union(y)
顺便说一下,你可以直接写 set()
来获取一个空集合,不需要写 set([])
。所以重写后的 reduce()
应该是:
reduce(lambda x, y: x.union(y), a, set())
其他人也提供了一些额外的选项,每个选项都有助于你思考它们的工作原理。