【问题标题】:Python stack overlapped element cumulationPython堆栈重叠元素累积
【发布时间】:2017-05-23 07:00:14
【问题描述】:

我想在 Python 的 Arraystack 上累积添加元素

class StockManager:

    __PROFIT = 0

    def __init__(self, o_name, o_surname):
        self.box = ArrayStack()
        self._name = o_name
        self._surname = o_surname

    def buy_shares(self, company, number, buy_price):
        StockManager.__PROFIT -= buy_price * number
        n = 0

        if len(self.box) < 2:
            """there is no overlapped elements when box has no element"""
            self.box.push(company) 
            self.box.push(number)
        else:
            while n < len(self.box):
               if self.box._data[n] == company:
               """every even index(n = 0, 2, 4, ...) refers to company name"""
               """every odd index(n = 1, 3, 5, ...), which is next to even index refers to number of buying"""
                    self.box._data[n + 1] += number
                    n += 2

               elif self.box._data[n] != company:
                    """ if there's no overlapping, then just put the elements """
                    self.box.push(company)
                    self.box.push(number)
                    n += 2
        return print(self.box._data)

而Arraystack类是这样的:

class ArrayStack:
    """LIFO Stack implementation using a Python list as underlying storage."""

    def __init__(self):
        """Create an empty stack."""
        self._data = []                       # nonpublic list instance

    def __len__(self):
        """Return the number of elements in the stack."""
        return len(self._data)

    def is_empty(self):
        """Return True if the stack is empty."""
        return len(self._data) == 0

    def push(self, e):
        """Add element e to the top of the stack."""
        self._data.append(e)                  # new item stored at end of list

    def top(self):
        """Return (but do not remove) the element at the top of the stack.

        Raise Empty exception if the stack is empty.
        """
        if self.is_empty():
            raise AssertionError('Stack is empty')
        return self._data[-1]                 # the last item in the list

    def pop(self):
        """Remove and return the element from the top of the stack (i.e., LIFO).

        Raise Empty exception if the stack is empty.
        """
        if self.is_empty():
            raise AssertionError('Stack is empty')
        return self._data.pop()               # remove last item from list

    def print_contents(self):
        print("Stack content: {0}".format(self._data))

当我运行 stockmanager 时

if __name__ == '__main__':
    P = StockManager("A","B")
    P.buy_shares("hyundai", 20, 100)
    P.buy_shares("hyundai", 20, 100)
    P.buy_shares("hyundai", 20, 100)
    P.buy_shares("lg", 20, 100)

结果是

['hyundai', 20]  => O.K
['hyundai', 40]  => O.K
['hyundai', 60]  => O.K
['hyundai', 60, 'lg', 40] => It should be ['hyundai', 60, 'lg', 20]
['hyundai', 60, 'lg', 60, 'lg', 40] => don't know why this result comes...

我该如何处理这个问题?

【问题讨论】:

  • 您到底想用buy_shares 中的while 循环来完成什么?
  • 另外,为什么要使用堆栈?为什么不是字典?
  • 啊,因为它是用于练习数据结构-堆栈-所以我制作并使用堆栈而不是字典。我也认为字典效率更高。

标签: python stack


【解决方案1】:

所以,问题在于您的while 循环:

           while n < len(self.box):
           if self.box._data[n] == company:
               """every even index(n = 0, 2, 4, ...) refers to company name"""
               """every odd index(n = 1, 3, 5, ...), which is next to even index refers to number of buying"""
               self.box._data[n + 1] += number
               n += 2

           elif self.box._data[n] != company:
               """ if there's no overlapping, then just put the elements """
               self.box.push(company)
               self.box.push(number)
               n += 2

想象一下我们已经跑了:

P = StockManager("A","B")
P.buy_shares("hyundai", 20, 100)
P.buy_shares("hyundai", 20, 100)
P.buy_shares("hyundai", 20, 100)

到目前为止,一切都按计划进行。现在,你试试:

P.buy_shares("lg", 20, 100)

所以:n == 0 和 len(self.box) == 2,所以我们进入循环。

if 条件失败,self.box._data[n] != 'lg',所以我们转到elif 块:

           self.box.push(company)
           self.box.push(number)
           n += 2

现在,box == ['hyundai', 60, 'lg', 20] 和 n == 2。可是等等!循环条件是n &lt; len(box),但是len(box) == 4,所以我们再次进入while循环!这一次,if 条件自self.box._data[2] == 'lg' 过去了这一次。

所以你执行 if 块的主体:

           self.box._data[n + 1] += number
           n += 2

现在,n == 4 和 box == ['hyundai', 60, 'lg', 40]。这一次,4 &lt; len(box) 失败,我们退出循环,你的函数结束。

现在,堆栈对我来说似乎是错误的数据结构。必须将大小增加两个是很笨重的。如果你真的想要这样做,我会建议像

这样的方法
offset = 0
i = -2
for i in range(0, len(self.box), 2):
    if self.box._data[n] == company:
        break
else:
    offset = 2
    self.box.push(company)
    self.box.push(0)
self.box._data[i + offset + 1] += number

但同样,这很笨重。你最好使用dict for box,然后逻辑可以简单地实现为:

self.box[company] = self.box.get(company, 0) + 1

或者更好的是,使用defaultdict

>>> from collections import defaultdict
>>> box = defaultdict(int)
>>> box
defaultdict(<class 'int'>, {})
>>> box['lg'] += 20
>>> box
defaultdict(<class 'int'>, {'lg': 20})
>>> box['lg'] += 20
>>> box
defaultdict(<class 'int'>, {'lg': 40})
>>> box['lg']
40

【讨论】:

  • 我认为 "for i (0, len(self.box), 2):" 在 python 3.5 中出现了语法错误
  • @S.JHahn 复制它时出错。它应该是for i in range(0, len(self.box), 2):
【解决方案2】:

您正在使用索引遍历整个列表;如果第一个company/number与您要购买的股票不匹配,它会自动附加到列表的末尾;然后下一组索引将指向刚刚添加的 new 公司,因此它添加了数字。 elif 不正确 - 在遍历整个列表但未找到之前,您不应添加新的 company/number 对。

这就是你正在做的事情

>>> a = ['a',1]
>>> n = 0
>>> comp, nbr = 'b', 2
>>> while n < len(a):
....    if a[n] == comp:
            print('comp found at', n) 
            a[n+1] += nbr
            n += 2
        else:
            print('n =', n, 'appending', comp) 
            a.append(comp)
            a.append(nbr)
            n += 2


n = 0 appending b
comp found at 2
>>>

这是你可以做的修复它:

>>> a = ['a',1]
>>> n = 0
>>> comp, nbr = 'b', 2
>>> while n < len(a):
        found = False
        if a[n] == comp:
            print('comp found at', n) 
            a[n+1] += nbr
            found = True
        n += 2


>>> if not found:
        a.append(comp)
        a.append(nbr)


>>> a
['a', 1, 'b', 2]
>>>

但正如 cmets 中所建议的,您最好将购买的内容存储在字典中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多