循环后避免重复代码?

mow*_*ker 15 python language-agnostic code-organization

在使用循环时,我经常最终写两次代码.例如,在浏览Udacity计算机科学课程时,我编写了代码(用于查找最顺序重复元素的函数):

def longest_repetition(l):
    if not l:
        return None
    most_reps = count = 0 
    longest = prv = None
    for i in l:
        if i == prv:
            count += 1
        else:
            if count > most_reps:
                longest = prv
                most_reps = count
            count = 1
        prv = i
    if count > most_reps:
        longest = prv
    return longest
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果计数大于先前重复的元素,我会检查两次.当当前元素与上一个元素不同以及当我到达列表末尾时,都会发生这种情况.

在按字符解析字符串时,我也遇到过这种情况.还有几次代码大约有5行代码.这是常见的,还是我思考/编码的结果.我该怎么办?

编辑:同样,在一个人为的字符串拆分示例中:

def split_by(string, delimeter):
    rtn = []
    tmp = ''
    for i in string:
        if i == delimeter:
            if tmp != '':
                rtn.append(tmp)
                tmp = ''
        else:
            tmp += i
    if tmp != '':
        rtn.append(tmp)
    return rtn
Run Code Online (Sandbox Code Playgroud)

编辑:这是来自该课程的学生,他们不会对Python有任何外部知识; 只有以前单位教过的东西.虽然我确实有过Python的经验,但我仍然试图遵循这些限制来充分利用这个课程.像str.split,列表和Python的许多基础知识这样的东西都被教过,但是还没有任何关于进口的东西 - 特别是像groupby这样的东西.话虽如此,如何在没有任何可能不会在编程入门课程中教授的语言特征的情况下编写.

Ult*_*nct 6

自从你标记后language-agnostic,我发现你对python特定的东西不太感兴趣,你可以使用这些东西来使你的代码高效,紧凑和可读.出于同样的原因,我不会展示在python中编写代码的漂亮程度.

在某些情况下,if根据您的算法可以避免最后的额外情况,但大多数情况下它就像"如果它存在,它应该是重要的和/或有效的".我不知道python解释器是如何工作的,但是在C/C++ /等编译语言中.编译器执行各种循环优化,包括如果它执行相同的操作,将if块移出循环.

我跑了并比较了各种片段的运行时间:

  • @JFSebastian - 8.9939801693
  • @srgerg - 3.13302302361
  • 你的 - 2.8182990551.

尾随if给你最好的时间并不是一种概括.我的观点是:只需按照您的算法,并尝试优化它.最后一点都没有错if.可能替代解决方案很昂贵.

关于您放入的第二个示例:检查tmp == ''完成以确保仅返回非空字符串.这实际上是分裂算法的一种附加条件.在任何情况下,rtn.append循环后都需要一个额外的,因为还有一些超出最后一个分隔符的东西.你总是可以在循环中推送一个if条件,就像if curCharIndex == lastIndex: push items to list在每次迭代中都会执行一样,并且它的类型再次相同.

我的答案简短:

  • 您的代码与您的算法一样高效.
  • if到底s的在许多情况下遇到的-没有必要担心他们,他们可能会使得代码比其他方法更有效没有这样的,如果(例子就在这里).
  • 此外,编译器还可以发现和修改/移动代码周围的块.
  • 如果有一个语言特性/库使您的代码快速且同时可读,请使用它.(其他答案在这里指出python提供的:))

  • 优化的第一条规则:**不要**.第二个 - *尚未*.[让它工作,做对,快速实现](http://c2.com/cgi/wiki?MakeItWorkMakeItRightMakeItFast). (2认同)

Wes*_*Wes 5

看看其实现itertools.groupby几乎完全符合您的要求.http://docs.python.org/library/itertools.html#itertools.groupby

这是使用所述代码的算法:

from itertools import groupby

string = "AAABBCCDDDD"

maximum = 0
max_char = ""

for i in groupby(string):
    x, xs = i
    n = len(list(xs))
    if n > maximum:
        max_char = x
        maximum = n

print max_char
Run Code Online (Sandbox Code Playgroud)

我考虑将来编写这样的算法的建议是尽量不要在一个函数中做所有事情.考虑解决您尝试解决的问题的较小函数,例如"将序列中相等项的每个序列分组为更小的序列".

当然,它也不一定是上述算法中的字符 - 它可以是任何可分组的.

编辑:为了响应OP的编辑,我想你不会在类设置中使用/了解像itertools这样的库,但我并不是说你应该依赖外部库,而是你应该考虑的更多通过将它们分成更小的子问题来解决问题.因此,在这种情况下,您将实现自己的groupby并使用它.


jfs*_*jfs 5

避免在循环后重复条件的语言不可知的技术是将前哨值附加到输入数据,例如,如果delimiter附加到末尾,string则在中不需要条件split_by()。典范示例:在线性搜索算法中,可以将针头附加到干草堆中,以避免结束序列检查。

另一种选择是将一些工作委派给一个单独的函数,例如,一个函数计算重复次数,另一个发现最大值,如longest_repetition()

from itertools import groupby

def longest_repetition(iterable):
    return max(groupby(iterable), key=lambda x: sum(1 for _ in x[1]))[0]
Run Code Online (Sandbox Code Playgroud)

如果重复的代码不重要;这可能不值得付出努力。