【问题标题】:handling building a string with a recursive function处理使用递归函数构建字符串
【发布时间】:2016-12-08 23:41:16
【问题描述】:

我有一个打印字符串的递归函数。 我希望函数返回它当前打印的字符串。

代码基本上在不同的递归级别打印出我想要的不同字符串。

我在考虑使用全局变量,但不认为这听起来很 Python。

我会在一个更大的程序中多次调用这个函数。

如果您想查看当前的代码:

def check_if_multiple_sections(the_string):
    level = 0
    counter = 0
    for char in the_string:
        if char == '(':
            level = level + 1
            if level == 0:
                counter = counter + 1
        if char == ')':
            level = level - 1
            if level == 0:
                counter = counter + 1
    return counter

def break_it_up(the_string):
    level = 0
    counter = 0
    break_points = []
    for char in the_string:
        if char == '(':
            level = level + 1
        if char == ')':
            level = level - 1
            if level == 0:
                break_points.append(counter + 1)
        counter = counter + 1
    return break_points


def recur_markov_change(the_string, key):
    #print("the_string: " + str(the_string) + " : key: " +str(key))
    if key is not None:
        #print(the_string)
        #print("YEA")
        print(str(the_string).split(' ')[0] +'^'+str(key) + ' ', end='')
    else:
        print('(TOP ', end ='')
    key = ((the_string.split(' '))[0])[1:]

    if len(the_string) < 2:
        return
    remaining_string = the_string.split(' ', 1)[1][:-1]
    results = []
    results.append(((remaining_string.split(' '))[0])[1:])
    level = 0
    counter = 0
    if the_string.count('(') == 1:
        items = the_string[1:-1]
        both = items.split(' ')
        print(str(the_string).split(' ',1)[1], end="") #This prints leaves
        return

    for char in remaining_string:
        if char == '(':
            level = level + 1
        if char == ')':
            level = level - 1
        if level == 0 and char == ' ':
            results.append(((remaining_string[counter+1:].split(' '))[0])[1:])
        counter = counter + 1
    answer = (key, results, remaining_string)
    #print(answer)

    if check_if_multiple_sections(remaining_string) > 1:
        break_points = break_it_up(remaining_string)
        sublines = []
        prev_spot = 0
        for breaks in break_points:
            sublines.append(remaining_string[prev_spot:breaks].strip())
            prev_spot = breaks
        sublines.append(remaining_string[breaks:].strip())
        for line in sublines:
            if len(line) > 2:
                print(' ', end='')
                recur_markov_change(line, key)
    print(')', end='')


given_string = '(TOP (SBARQ (WHNP_WDT  Which) (SQ_VP (VBZ  is) (ADJP_JJ  last))) (PUNC  ?))'
string_that_I_want_function_to_return = '(TOP (SBARQ^TOP (WHNP_WDT^SBARQ  Which) (SQ_VP^SBARQ (VBZ^SQ_VP  is) (ADJP_JJ^SQ_VP  last))) (PUNC^TOP  ?))'

recur_markov_change(given_string, None)
print("\ndesired string:")
print(string_that_I_want_function_to_return)

【问题讨论】:

  • 你能在某处放一个输入和输出的例子吗?
  • 如果您复制并粘贴所有代码,在底部它将调用该函数,该函数将打印我想要的内容。 @Pythogen
  • 我想,但我不知道如何在 @AER 函数之外获取它
  • 是的。问题是我如何让函数返回打印的字符串而不是打印它。
  • 我现在喜欢全局变量的声音。哈哈。

标签: python python-3.x recursion


【解决方案1】:

首先我添加了一个函数递归添加的基本字符串。我将其称为 initial ,然后将所有打印件替换为 inititial+= ,最后返回 initial

def check_if_multiple_sections(the_string):
    level = 0
    counter = 0
    for char in the_string:
        if char == '(':
            level = level + 1
            if level == 0:
                counter = counter + 1
        if char == ')':
            level = level - 1
            if level == 0:
                counter = counter + 1
    return counter

def break_it_up(the_string):
    level = 0
    counter = 0
    break_points = []
    for char in the_string:
        if char == '(':
            level = level + 1
        if char == ')':
            level = level - 1
            if level == 0:
                break_points.append(counter + 1)
        counter = counter + 1
    return break_points


def recur_markov_change(the_string, key, initial):
    #initial+=("the_string: " + str(the_string) + " : key: " +str(key))
    if key is not None:
        #initial+=(the_string)
        #initial+=("YEA")
        initial+=(str(the_string).split(' ')[0] +'^'+str(key) + ' ')
    else:
        initial+=('(TOP ')
    key = ((the_string.split(' '))[0])[1:]

    if len(the_string) < 2:
        return
    remaining_string = the_string.split(' ', 1)[1][:-1]
    results = []
    results.append(((remaining_string.split(' '))[0])[1:])
    level = 0
    counter = 0
    if the_string.count('(') == 1:
        items = the_string[1:-1]
        both = items.split(' ')
        initial+=(str(the_string).split(' ',1)[1]) #This initial+=s leaves
        return initial

    for char in remaining_string:
        if char == '(':
            level = level + 1
        if char == ')':
            level = level - 1
        if level == 0 and char == ' ':
            results.append(((remaining_string[counter+1:].split(' '))[0])[1:])
        counter = counter + 1
    answer = (key, results, remaining_string)
    #initial+=(answer)

    if check_if_multiple_sections(remaining_string) > 1:
        break_points = break_it_up(remaining_string)
        sublines = []
        prev_spot = 0
        for breaks in break_points:
            sublines.append(remaining_string[prev_spot:breaks].strip())
            prev_spot = breaks
        sublines.append(remaining_string[breaks:].strip())
        for line in sublines:
            if len(line) > 2:
                initial+=(' ')
                initial = recur_markov_change(line, key, initial)
    initial+=(')')
    return initial


given_string = '(TOP (SBARQ (WHNP_WDT  Which) (SQ_VP (VBZ  is) (ADJP_JJ  last))) (PUNC  ?))'
string_that_I_want_function_to_return = '(TOP (SBARQ^TOP (WHNP_WDT^SBARQ  Which) (SQ_VP^SBARQ (VBZ^SQ_VP  is) (ADJP_JJ^SQ_VP  last))) (PUNC^TOP  ?))'

print(recur_markov_change(given_string, None, ""))
print("\ndesired string:")
print(string_that_I_want_function_to_return)

测试和工作对我来说就像一个魅力

【讨论】:

  • 我在这个解决方案中看不到递归过程或递归过程。
  • 请见谅,如果我太苛刻了,但我相信你是盲目的,在最后一个返回语句上方两行:initial = recur_markov_change(line, key, initial)
  • 抱歉,我在找return current_function(...)
【解决方案2】:

...This would be impossible without recursion.., - 无需递归即可。

import collectons, operator
s = '(TOP (SBARQ (WHNP_WDT  Which) (SQ_VP (VBZ  is) (ADJP_JJ  last))) (PUNC  ?))'
result = '(TOP (SBARQ^TOP (WHNP_WDT^SBARQ  Which) (SQ_VP^SBARQ (VBZ^SQ_VP  is) (ADJP_JJ^SQ_VP  last))) (PUNC^TOP  ?))'

我将使用一个类 Node 和一个自定义的 ___str___ 方法。节点的有效负载可以是其他节点,也可以是 innermost 节点的字符串。

class Node:
    def __init__(self, name, index):
        self.name = name
        self.index = index
        self.parent = None
        self._payload = []
    @property
    def payload(self):
        return self._payload
    @payload.setter
    def payload(self, thing):
        self._payload.append(thing)
    def __str__(self):
        if self.parent is not None:
            name = '{}^{}'.format(self.name, self.parent.name)
        else:
            name = self.name
        #account for the extra space in a non-Node paylode
        if not isinstance(self.payload[0], Node):
            payload = ' ' + self.payload[0]
        else:
            payload = ' '.join(str(thing) for thing in self.payload)
        return '({!s:} {!s:})'.format(name, payload)

该函数首先找到所有左右括号的索引。如果左括号后面跟着左括号,则创建一个 unfinished 节点。 当找到左/右括号对时,节点已被完全解析(完成)。它返回最外层的节点。

def parse(s):
    # Where are the parenthesis?
    unfinished_nodes = collections.deque()
    left, right = collections.deque(), collections.deque()
    for i, c in enumerate(s):
        if c == '(':
            left.append(i)
        if c == ')':
            right.append(i)

    if len(left) != len(right):
        raise ValueError('Unbalanced parenthesis in s')

    # helpers
    paren = operator.itemgetter(0)
    next_paren = operator.itemgetter(1)

    while left and right:
        while paren(left) > paren(right):
            # back-up to previous Node
            left.rotate()
        #print('left:{}, right:{}'.format(paren(left), paren(right)))
        # are we at the bottom? No more Nodes?
        try:
            if next_paren(left) < paren(left):
                finished = True
            else:
                finished = paren(left) < paren(right) < next_paren(left)
        except IndexError:
            # only one more left paren - outermost Node
            finished = True
        if finished:
            token = s[paren(left)+1:paren(right)]
            #print('\ttoken:{}'.format(token))
            if '(' not in token:
                # this is an inner Node
                name, payload = token.split()
                node = Node(name, paren(left))
                node.payload = payload
                try:
                    node.parent = unfinished_nodes[-1]
                    node.parent.payload = node
                except IndexError:
                    # this inner Node is the first Node in the sequence
                    pass
                unfinished_nodes.append(node)
            # finished is the outermost completely parsed node
            finished = unfinished_nodes.pop()
            #print('\tfinished:{!s:}'.format(finished.name))
            right.popleft()
            left.popleft()
            #print('\t\tL:{}\t\tR:{}'.format(left, right))
        else:
            name = s[paren(left)+1:next_paren(left)]
            name = name.strip()
            node = Node(name, paren(left))
            try:
                node.parent = unfinished_nodes[-1]
                node.parent.payload = node
            except IndexError:
                # this is the outermost Node
                pass
            #print('\tnew Unfinished:{}'.format(node.name))
            unfinished_nodes.append(node)
            # proceed to the next Node
            left.rotate(-1)
    return finished
    #or if you prefer
    #return str(finished)

print(parse(s))
print(result)

这里是简化的,没有任何恶作剧,非递归,输入字符串一次传递 - 快速,干净,高效:

import collections
def parse2(s):
    parents = collections.deque()
    final = collections.deque()
    t = ''
    new_parent = False
    new = ''
    for c in s:
        if c == '(':
            new_parent = True
            t += c
        elif c == ')':
            t += c
            final.append(t)
            t = ''
            parents.pop()
        else:
            if c == ' ' and new_parent:
                if parents:
                    t = t + '^' + parents[-1]
                parents.append(new)
                new_parent = False
                new = ''
            elif new_parent:
                new += c
            t += c
    return ''.join(final)

不知道是什么让我想出了第一个使用 Node 类的解决方案,并将其视为一棵树/图形/任何东西。

【讨论】:

    猜你喜欢
    • 2021-03-24
    • 2017-10-08
    • 2014-01-01
    • 2019-12-21
    • 2019-06-03
    • 2013-02-25
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多