查找列表中连续增加的元素的数量

时间:2013-12-14 12:45:57

标签: python python-2.7

我在TalentBuddy遇到了一个问题,听起来像这样

  

学生在实验室活动中的表现应该始终有所改善,但情况并非总是如此。   由于进步是学生最重要的指标之一,让我们编写一个程序,计算任何特定学生的最长时间的表现。   例如,如果他在课程中所有实验室活动的成绩分别为:9,7,8,2,5,5,8,7,那么最长的时间将是4个连续的实验室(2,5,5,8)。 / p>

到目前为止,我似乎对编写代码感到困惑。我唯一工作的是

def longest_improvement(grades):
    res = 0
    for i in xrange(len(grades) - 2):
        while grades[i] <= grades[i + 1]:
            res += 1
            i += 1
    print res

但在17时打印6而不是grades = [1, 7, 2, 5, 6, 9, 11, 11, 1, 6, 1]

如何解决剩下的代码?感谢

7 个答案:

答案 0 :(得分:3)

解决了一些老式的尾递归:

grades = [1, 7, 2, 5, 6, 9, 11, 11, 1, 6, 1]

def streak(grades):
    def streak_rec(longest, challenger, previous, rest):
        if rest == []:             # Base case
            return max(longest, challenger)
        elif previous <= rest[0]:  # Streak continues
            return streak_rec(longest, challenger + 1, rest[0], rest[1:])
        else:                      # Streak is reset
            return streak_rec(max(longest, challenger), 1, rest[0], rest[1:])

    return streak_rec(0, 0, 0, grades)

print streak(grades) # => 6
print streak([2])    # => 1

答案 1 :(得分:1)

由于当前的解决方案涉及到产量和映射以及额外的内存开销,因此至少提一下这个简单的解决方案可能是一个好主意:

def length_of_longest_sublist(lst):
    max_length, cur_length = 1, 1
    prev_val = lst[0]
    for val in lst[1:]:
        if val >= prev_val :
            cur_length += 1
        else:
            max_length = max(max_length, cur_length)
            cur_length = 1
        prev_val = val
    return max(max_length, cur_length)

我们可以通过直接获取前一个值来减少该代码:

def length_of_longest_sublist2(lst):
    max_length, cur_length = int(bool(lst)), int(bool(lst)) 
    for prev_val, val in zip(lst, lst[1:]):
        if val >= prev_val:
            cur_length += 1
        else:
            max_length = max(max_length, cur_length)
            cur_length = 1
    return max(max_length, cur_length)

这是一个很好的技巧(并且允许它轻松地为空列表返回正确的结果),但对于不了解这些习语的人来说会让人感到困惑。

答案 2 :(得分:1)

我会这样解决:

from itertools import groupby
from funcy import pairwise, ilen 

def streak(grades):
    if len(grades) <= 1: 
        return len(grades)
    orders = (x <= y for x, y in pairwise(grades))
    return max(ilen(l) for asc, l in groupby(orders) if asc) + 1

非常明确:orders是升序对True的迭代器,降序对False的迭代器。然后我们只需找到一个最长的升序列表并添加1。

答案 3 :(得分:0)

您在内部res循环的每次迭代中使用相同的while变量。您可能想要重置它,并将最高的中间结果保存在不同的变量中。

答案 4 :(得分:0)

有点晚了,但这是我的更新版本:

from funcy import ilen, ireductions


def streak(last, x):
    if last and x >= last[-1]:
        last.append(x)
        return last
    return [x]


def longest_streak(grades):
    xs = map(ilen, ireductions(streak, grades, None))
    return xs and max(xs) or 1

grades = [1, 7, 2, 5, 6, 9, 11, 11, 1, 6, 1]
print longest_streak(grades)
print longest_streak([2])

我最终决定不仅产生正确的 没有错误的版本,但使用我非常喜欢funcy的库:)

<强>输出:

6
1

答案 5 :(得分:0)

可能没有以前的答案那么有效,但它很简短:P

diffgrades = np.diff(grades)
maxlen = max([len(list(g)) for k,g in groupby(diffgrades, lambda x: x >= 0) if k]) + 1

答案 6 :(得分:0)

基于@ M4rtini使用itertools.groupby的想法。

def longest_streak(grades):
    from itertools import groupby    
    if len(grade) > 1:
        streak = [x <= y for x, y in zip(grades,grades[1:])]
        return max([sum(g, 1) for k, g in groupby(streak) if k])
    else:
        return len(grades)