当我用 python 编写代码时,我总是尝试像使用 F# 一样思考替代方案:
我有一个seq
元组,(key, value1, value2, ...)
我在这里简化了元组,所以它的长度只有 2。键包含重复的数字。
let xs = Seq.zip [|1;2;2;3;3;3;4;1;1;2;2|] {0..10} // so this is a seq of tuple
[(1, 0),
(2, 1),
(2, 2),
(3, 3),
(3, 4),
(3, 5),
(4, 6),
(1, 7),
(1, 8),
(2, 9),
(2, 10)]
现在,我想构建一个函数,它将seq
作为输入,并返回 a seq
,它是原始 seq 的子集。
它必须捕获所有更改键的项目,并包括第一个和最后一个项目,seq
如果它们不存在的话。
f1(xs) = [(1, 0), (2, 1), (3, 3), (4, 6), (1, 7), (2, 9), (2, 10)]
f1([]) = []
以下是我的 python 代码,它可以工作,但我不太喜欢它。
xs = zip([1,2,2,3,3,3,4,1,1,2,2], range(11))
def f1(xs):
if not xs:
return
last_a = None # I wish I don't have to use None here.
is_yield = False
for a, b in xs:
if a != last_a:
last_a = a
is_yield = True
yield (a, b)
else:
is_yield = False
if not is_yield:
yield (a, b) # Ugly, use variable outside the loop.
print list(f1(xs))
print list(f1([]))
这是另一种方式,使用itertools
库
def f1(xs):
group = None
for _, group_iter in itertools.groupby(xs, key = lambda pair: pair[0]):
group = list(group_iter)
yield group[0]
# make sure we yield xs[-1], doesn't work if xs is iterator.
if group and len(group) > 1: # again, ugly, use variable outside the loop.
yield group[-1]
在 F# 中,与 python 中Seq.groupBy
的行为不同groupby
。我想知道如何尽可能地解决这个问题,减少参考单元,减少mutable
,并且没有太多麻烦。