Питонический способ вытолкнуть элементы из стека (collection.deque) - PullRequest
0 голосов
/ 02 июня 2018

TL; DR: см. Код внизу.

Я реализую калькулятор обратной польской записи в Python, используя реализацию стека collection.deque .

Поскольку я обрабатываю также случай функций с несколькими аргументами, я использую символ-разделитель, который ставлю перед фактическими аргументами.Например, учитывая следующее выражение в качестве входных данных: max(2, 3, 4), алгоритм Shunting Yard создает следующую итерацию: ['|', '2', '3', '4', 'max'].

Когда я итерирую по нему, разделитель и числапомещаются в стек;если встречается функция, все предыдущие элементы до разделителя «выталкиваются» из стека и добавляются в список.

Есть ли более питонный способ выталкивать элементы из конца стекадо определенного состояния?Мой код пока:

args = []
while op_stack[-1] != FUNC_ARGS_SEPARATOR:
    args.append(op_stack.pop())

Ответы [ 3 ]

0 голосов
/ 02 июня 2018

Вот еще одно решение с итераторами.Я бы не назвал это улучшением по сравнению с вашим текущим решением, но оно отличается.

from collections import deque
import itertools

d = deque(["|", "2", "3", "4", "max"])

args = list(
    itertools.takewhile(
        # Check if elt is a separator.
        # Side-effect: append separator if encountered.
        lambda elt: elt != "|" or d.append(elt),
        # Pop forever.
        (d.pop() for _ in itertools.repeat(None)),
    )
)
0 голосов
/ 02 июня 2018

С помощью друга мы получили ключевое слово iter с sep как sentinel :

from collections import deque

sep = "|"
op_stack = deque([sep, 2, 3, 4])

args = iter(op_stack.pop, sep)

print(list(args))

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

Спасибо за помощь, ребята!

0 голосов
/ 02 июня 2018

То, что у тебя есть, хорошо;нет разумного способа выполнить эту задачу с помощью протокола итератора (который обычно используется для очистки подобных вещей).

Теоретически, если вы изменили порядок своих op_stack (так чтоверхняя часть была слева, а не справа), вы можете использовать .index для поиска разделителя, затем выполнить массовый срез и args.extend, затем массовый срез del, но это вряд ли стоит того (особенно когда разделитель может быть найден относительно быстро).

...