2017-01-09 2 views
1

Я хочу кумулятивно добавить элемент на Arraystack в Pythonстек Python перекрывающийся элемент кумуляции

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... 

Как я могу справиться с этой проблемой?

+0

Что именно вы пытаетесь выполнить с помощью цикла while в 'buy_shares'? –

+1

Кроме того, зачем использовать стек? Почему не словарь? –

+0

Ах, поскольку он предназначен для использования данных strucutre - 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 < len(box), но len(box) == 4, поэтому мы снова вводим цикл while! На этот раз условия if проходят с self.box._data[2] == 'lg'.

Так вы выполняете тело из-если блок:

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

Теперь n == 4 и box == ['hyundai', 60, 'lg', 40]. На этот раз 4 < 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 для коробки, то логика может быть реализована просто:

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 
+0

thx много для вашего вида и полезных ответов! –

+0

Я думаю, «для i (0, len (self.box), 2):« сделал грамматическую ошибку в python 3.5 –

+0

@ S.JHahn это была ошибка, когда я ее скопировал. Он должен читать 'for i in range (0, len (self.box), 2):' –

0

Вы итерация всего списка с использованием индексов ; если первый company/number не соответствует запасам, которые вы покупаете, он автоматически добавляется в конец списка; то следующий набор индексов будет указывать на новую компанию, которая была просто добавлена, чтобы добавить номер. 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] 
>>> 

Но как это было предложено в комментариях, вы, вероятно, будет лучше сохраняя покупку в словаре.

+0

Также спасибо! –

Смежные вопросы