0

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

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,因为它是序列中唯一从列表的第一个索引单调递减的部分。

很抱歉解释的困难。预先感谢您的帮助!

4

4 回答 4

0

您可以使用 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
于 2016-08-02T14:30:15.833 回答
0

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

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- 最后一个元素的索引。

于 2016-08-02T14:13:59.330 回答
0

如果你想让事情变得过于复杂,你可以首先创建一个函数,在迭代中生成连续条目对:

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

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

于 2016-08-02T15:07:18.417 回答
0

如果[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
于 2016-08-02T17:03:27.257 回答