【问题标题】:Checking monotonicity of subsequences in Python在 Python 中检查子序列的单调性
【发布时间】:2016-08-02 14:08:35
【问题描述】:

我希望能够找到单调递减子序列末尾的索引,该子序列从列表的第一个索引开始,并且仅按连续顺序下降。例如,我可能有一个如下所示的列表:

x = [89, 88, 88, 88, 88, 87, 88] 我希望能够返回5 因为它是子序列[89, 88, 88, 88, 88, 87] 的最后一个元素的索引,其中该子序列中的每个数字都是单调递减并连续下降,开始89,列表的第一个索引。

例如,我有一个如下所示的列表:x = [89, 87, 87, 86, 87]。我想返回0,因为它是唯一以第一个索引 (89) 开头的数字,并且连续单调递减(即列表中的下一个数字从第一个数字下降 2)。或者,如果我有一个看起来像这样的列表:x = [89, 90, 89, 88],我想返回0,因为它是序列中唯一从列表的第一个索引单调递减的部分。

抱歉,难以解释。提前感谢您的帮助!

【问题讨论】:

  • 到目前为止你尝试过什么?这不是一个供人们为您编写代码的网站-
  • 试一试,如果您遇到问题,请发布您的尝试和遇到的问题。乍一看,您似乎想从索引 i 中减去索引 i+1 并找到结果为负的位置 - 这应该足以解决问题。
  • 对于连续函数,导数用于分析它如何在域中变化。导数的离散类似物是finite difference。您似乎想根据数据系列的计算有限差分返回值。
  • @sos 如果您有一个您认为效率低下的有效解决方案,那么您应该在 codereview.stackexchange.com 上询问(一个主题问题)。这里不是询问一般实施想法的地方。
  • 请注意,当前形式的这个问题与代码审查无关。我们正在改进现有的工作代码。

标签: python subsequence


【解决方案1】:

我不确定我是否完全理解了这个问题,但请看一下:

def findseries(a):
    for i in xrange(len(a) - 1):
        if a[i+1] - a[i] not in [-1, 0]:
            return i
    return len(a) - 1

您基本上是遍历列表。如果您检查的下一个元素不是恰好比当前元素小 1 或等于它,那么我们知道当前元素将是系列中的最后一个元素。

否则,我们继续下一个元素。

如果我们已经完成了整个列表的迭代而没有找到任何不匹配的元素,我们可以说列表的最后一个元素是系列的最后一个元素,所以我们返回len(a) - 1 - 最后一个元素的索引。

【讨论】:

  • 谢谢!几乎是我要找的。但我不一定想要列表中的最后一个元素。只有列表子集的最后一个单调连续递减的元素。
  • “但我不一定想要列表中的最后一个元素”是什么意思?仅当整个列表是正确的系列(单调连续递减)时,此函数才返回列表的最后一个元素
  • 这是不正确的。 if 条件应该是 a[i+1]-a[i] not in [-1,0]
  • @SauravGupta 确实你是对的。固定的 :)。忘记了元素可以等于他们以前的;-)
  • 从单个序列中迭代相邻对的便捷方法是:for x, y in zip(a, a[1:]):
【解决方案2】:

如果你想把事情复杂化,你可以先创建一个函数,在可迭代对象中生成连续条目对:

def consecutive_pairs(iterable):
    it = iter(iterable)
    first = next(it)
    for second in it:
        yield (first, second)
        first = second

然后,你可以检查每一对的差是0还是1:

def last_decreasing_index(iterable):
    pairs = consecutive_pairs(iterable)
    for index, (first, second) in enumerate(pairs):
        if first - second not in (0, 1):
            return index
    return index + 1 # full sequence is monotonic

显然有更短的方法可以实现相同的目标(请参阅其他答案)。

【讨论】:

    【解决方案3】:

    如果[88,88,88] 产生 2,则此方法有效:

    def foo(it, n = 0):
        #print(it, n)
        try:
            monotonic = -1 < it[0] - it[1] < 2
            if monotonic:
                n = foo(it[1:], n + 1)
        except IndexError:
            pass
        return n
    

    重构 [88,88,88] 输入产生 0:

    def foo(it, n = 0):
        print(it, n)
        try:
            difference = it[0] - it[1]
            if difference == 0 and n == 0:
                pass
            elif -1 < difference < 2:
                n = foo(it[1:], n + 1)
        except IndexError:
            pass
        return n
    

    【讨论】:

      【解决方案4】:

      您可以使用 python 生成器表达式:

      x = [89, 88, 88, 88, 88, 87, 88]
      g = (i for i,(v,u) in enumerate(zip(x,x[1:])) if not (u+1==v or u==v))
      next(g)
      #output:
      5
      

      【讨论】:

      • 或者可能是next(g, -1)next(g, len(x)),这取决于在整个序列符合要求的情况下应该发生什么。
      猜你喜欢
      • 2011-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-04
      • 2018-09-23
      • 1970-01-01
      • 2012-11-09
      • 2017-12-13
      相关资源
      最近更新 更多