【问题标题】:Circular Buffer Python implementation循环缓冲区 Python 实现
【发布时间】:2013-07-02 19:12:56
【问题描述】:

我为一个 interviewstreet 问题编写了循环缓冲区的代码。但事实上,两个测试用例通过了,而其他的则失败了。失败原因:索引出f范围。之后我尝试了几个测试用例来重现失败。不幸的是,他们都没有重现错误。这是代码。

实现一个大小为 N 的循环缓冲区。允许调用者附加、删除和列出缓冲区的内容。实施缓冲区以实现每个操作的最大性能。

"A" n - 将以下 n 行附加到缓冲区。如果缓冲区已满,它们会替换旧条目。
"R" n - 删除缓冲区的前 n 个元素。这 n 个元素是当前元素中最早添加的元素。
"L" - 按插入时间的顺序列出缓冲区的元素。
“Q” - 退出。

class circbuffer():

    #initialization
    def __init__(self,size):
            self.maximum=size
            self.data=[]
            self.current=0


    #appending when the buffer is not full
    def append(self,x):
            if len(self.data)==self.maximum:
                    self.current=0
                    self.data[self.current]=x
                    self.current=(self.current+1)%self.maximum
                    self.__class__=bufferfull
            else:
                    self.data.append(x)

    def remove(self,x):
            if self.data:
                    self.data.pop(0)

    def cget(self):
            return self.data

class bufferfull:

    def append(self,x):
            if len(self.data)<self.maximum:
                    self.data.insert(self.current, x)
            else:
                    self.data[self.current]=x
            self.current=(self.current+1)%self.maximum

    def remove(self,x):
            if self.data:
                    if self.current>len(self.data):
                            self.current=0
                    self.data.pop(self.current)

    def cget(self):
            return self.data[self.current:]+self.data[:self.current]
n=input()

buf=circbuffer(n)
outputbuf=[]

while True:
    com=raw_input().split(' ')
    if com[0]=='A':
            n=int(com[1])
            cominput=[]
            for i in xrange(n):
                    cominput.append(raw_input())
            for j in cominput:
                    buf.append(j)
    elif com[0]=="R":
            n=int(com[1])
            for i in range(n):
                    buf.remove(i)
    elif com[0]=="L":
            for i in buf.cget():
                    outputbuf.append(i)
    elif com[0]=="Q":
            break

for i in outputbuf:
    print i

错误指向缓冲区满类中的self.data.pop(self.current)。我无法从采访街的人那里得到测试数据。我正在尝试自己想出测试用例来重现错误。

有什么见解吗?

【问题讨论】:

  • 我认为您在处理 self.__class__ 业务时给自己造成了不必要的困难。
  • @NPE,我必须同意你的看法。我是 Python 新手,将一个类分配给另一个类让我非常兴奋。实际上我迷恋 Python ..:) !如果有更好的方法,我将非常感谢您的帮助!
  • 与您已经熟悉您的代码相比,我们提出合适的测试用例的机会更少......
  • 保持简单。 不要当你可以在相同数量的行中直截了当时变得聪明。您只需要一个头指针、一个尾指针和一个固定大小的列表。你不需要任何花哨的元编程东西。
  • 分配给__class__ 是愚蠢的。设计模式(在这里,您可以使用 策略 做同样的事情)可能看起来像古怪的过度设计,但它们传达了拐点的目的,并且不太可能在你的脸上爆炸。

标签: python circular-buffer


【解决方案1】:

这里有一个错误:

def remove(self,x):
        if self.data:
                if self.current>len(self.data):
                        self.current=0
                self.data.pop(self.current)

如果self.current == len(self.data),你会尝试弹出一个不存在的元素。

一般来说,您的实现太复杂了,因此在我的书中得分不会很高(其他人可能会有不同的看法)。 @9000 对您的问题的评论很好地总结了它:

保持简单。当你可以在相同数量的行中直截了当时,不要聪明。您只需要一个头指针、一个尾指针和一个固定大小的列表。你不需要任何花哨的元编程东西。 – @9000

【讨论】:

  • 我受宠若惊 :) 这些词在我看来是如此通用/常识,以至于它们不需要仔细归因。我肯定在重复无数工程师在我之前说过同样的话。
【解决方案2】:

您似乎正在尝试使用下面的代码来阻止 index out of range 错误,但您检查的条件是错误的。

if self.current > len(self.data):
    self.current = 0
self.data.pop(self.current)

如果您调用self.data.pop(len(self.data)),您肯定会收到该错误,因为列表是 0 索引的。您可能的意思是:

if self.current >= len(self.data):
    self.current = 0
self.data.pop(self.current)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2010-10-24
    • 1970-01-01
    相关资源
    最近更新 更多