过滤掉列表中稳定值的更多 pythonic 方法

More pythonic way of filtering out stable values in a list

我编写了一个函数,允许我 运行 遍历列表,将值与前辈进行比较,并断言此时列表对于一定数量的条目变为 "stable"。 列表中的值代表一个信号,可能会或不会达到稳定点。 我想到了这个:

def unstableFor(points, maxStable):
    count = 0;
    prev = points[0]
    for i in range(1, len(points)):
        if points[i] == prev:
            count = count + 1
        else:
            count = 0
            prev = points[i]
        if count >= maxStable:
            return i
    return len(points) - 1

返回值随后被调用者用于删除列表的最后部分。

它完成了它的工作,但是,我对它看起来多么笨重很不满意。您能想出一种更 Pythonic 的、可能是纯函数式的方式来执行此过滤操作吗?

使用枚举和压缩:

def unstableFor (points, threshold):
    for i, (a, b) in enumerate(zip(points, points[1:])):
        count = count + 1 if a == b else 0
        if count >= threshold:
            return i
    return i

这是函数式方法的草图。这有点神秘。事实上,我可能会使用你的方法(使用 enumerate 作为惯用的方式而不是 range(len(x)))。无论如何,假设 max_stable 是 3:

>>> from itertools import groupby
>>> grouped = groupby(enumerate(x), lambda i_e: i_e[1])
>>> gen = (g for g in map(lambda e: list(e[1]), grouped) if len(g) >= 3)
>>> run = next(gen)
>>> run[2][0]
10

清理完毕:

>>> from operator import itemgetter
>>> from itertools import islice
>>> def unstable_for(points, max_stable):
...     grouped = groupby(enumerate(points), itemgetter(1))
...     gen = (g for g in (tuple(gg) for _, gg in grouped) if len(g) >= max_stable)
...     run = tuple(islice(gen,1))
...     if len(run) == 0:
...         return len(points) - 1
...     else:
...         return run[0][max_stable - 1][0]
...
>>> x
[1, 2, 3, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9]
>>> unstable_for(x, 3)
10
>>> unstable_for(x, 2)
3
>>> unstable_for(x, 1)
0
>>> unstable_for(x, 20)
13
>>>

不太优雅。同样,我会选择命令式解决方案。不过,也许有人有更优雅的功能解决方案。

我觉得你的代码很好:它易于阅读和理解。我只是删除一些重复,使它看起来像:

def unstableFor(points, maxStable):
    prev = None  # assuming None is not member of points
    for i, point in enumerate(points):
        if point == prev:
            count = count + 1
        else:
            count = 0
            prev = point
        if count >= maxStable:
            break
    return i