【问题标题】:replacing values in a nested tuple with the whole tuple用整个元组替换嵌套元组中的值
【发布时间】:2012-04-22 06:44:18
【问题描述】:

好的,

我正在研究语言证明器,并且我有一系列表示语句或表达式的元组。 有时,我最终得到一个嵌入的“和”语句,我试图将它“冒泡”到表面。 我想要一个看起来像这样的元组:

('pred', ('and', 'a', 'b'), 'x')

或者,举个更简单的例子:

( ('and', 'a', 'b'), 'x')

我想将 ands 分成两个语句,这样最上面的语句会产生:

('and', ('pred', 'a', 'x',), ('pred', 'b', 'x') )

和底部的:

('and', ('a', 'x'), ('b', 'x') )

我尝试了很多东西,但结果总是很丑陋的代码。如果有更多嵌套元组,我会遇到问题,例如:

('not', ('p', ('and', 'a', 'b'), 'x') )

我想要的结果

('not', ('and', ('p', 'a', 'x',), ('p', 'b', 'x') ) )

所以基本上,问题是试图用整个元组的值替换嵌套元组,但嵌套的元组被修改了。这是非常丑陋的。 :(

我不是超级流利的python,所以它变得非常复杂,有很多我知道不应该存在的for循环。 :( 非常感谢任何帮助!

【问题讨论】:

  • 很难处理这些tuples 没有真正的数据类型可以使用
  • 对不起,它们里面的一切都是一个字符串。是这个意思吗?
  • 哦,好吧,我不知道,因为没有引号,你说它们是tuples
  • 啊,我刚刚意识到表示令人困惑。它们不完全是元组,而是一个表达式类,我对其 repr 进行了修改以跳过打印中的逗号。我现在会解决这个问题。谢谢。
  • ('not',('and','a','b')) 的期望结果是什么?它应该变成('and',('not','a'),('not','b')),还是('or',('not','a'),('not','b')),还是保持原样?是否还有其他具有非标准行为的运算符(?)? (即,它的行为与 ( ('and', 'a', 'b'), 'x') 案例不同?)

标签: python tuples linguistics


【解决方案1】:

这种递归方法似乎有效。

def recursive_bubble_ands_up(expr):
    """ Bubble all 'and's in the expression up one level, no matter how nested.
    """
    # if the expression is just a single thing, like 'a', just return it. 
    if is_atomic(expr):
        return expr
    # if it has an 'and' in one of its subexpressions 
    #  (but the subexpression isn't just the 'and' operator itself)
    #  rewrite it to bubble the and up
    and_clauses = [('and' in subexpr and not is_atomic(subexpr)) 
                   for subexpr in expr]
    if any(and_clauses):
        first_and_clause = and_clauses.index(True)
        expr_before_and = expr[:first_and_clause]
        expr_after_and = expr[first_and_clause+1:]
        and_parts = expr[first_and_clause][1:]
        expr = ('and',) + tuple([expr_before_and + (and_part,) + expr_after_and 
                                 for and_part in and_parts])
    # apply recursive_bubble_ands_up to all the elements and return result
    return tuple([recursive_bubble_ands_up(subexpr) for subexpr in expr])

def is_atomic(expr):
    """ Return True if expr is an undividable component 
    (operator or value, like 'and' or 'a'). """
    # not sure how this should be implemented in the real case, 
    #  if you're not really just working on strings
    return isinstance(expr, str)

适用于您的所有示例:

>>> tmp.recursive_bubble_ands_up(('pred', ('and', 'a', 'b'), 'x'))
('and', ('pred', 'a', 'x'), ('pred', 'b', 'x'))
>>> tmp.recursive_bubble_ands_up(( ('and', 'a', 'b'), 'x'))
('and', ('a', 'x'), ('b', 'x'))
>>> tmp.recursive_bubble_ands_up(('not', ('p', ('and', 'a', 'b'), 'x') ))
('not', ('and', ('p', 'a', 'x'), ('p', 'b', 'x')))

请注意,这不知道任何其他“特殊”运算符,例如 not - 正如我在评论中所说,我不确定它应该如何处理。但它应该给你一些开始。

编辑:哦,哎呀,我刚刚意识到这只会执行一次“冒泡”操作,例如:

>>> tmp.recursive_bubble_ands_up(((('and', 'a', 'b'), 'x'), 'y' ))
(('and', ('a', 'x'), ('b', 'x')), 'y')
>>> tmp.recursive_bubble_ands_up((('and', ('a', 'x'), ('b', 'x')), 'y'))
('and', (('a', 'x'), 'y'), (('b', 'x'), 'y'))

所以你真正想要的可能是在一个while循环中应用它,直到输出与输入相同,如果你想让你的'and'从多个级别冒泡,就像这样:

def repeat_bubble_until_finished(expr):
    """ Repeat recursive_bubble_ands_up until there's no change 
    (i.e. until all possible bubbling has been done). 
    """
    while True:
        old_expr = expr
        expr = recursive_bubble_ands_up(old_expr)
        if expr == old_expr:
            break
    return expr

另一方面,这样做表明我的程序实际上破坏了你的“非”示例,因为它在“非”之前冒泡了“和”,你说你不想管它:

>>> tmp.recursive_bubble_ands_up(('not', ('p', ('and', 'a', 'b'), 'x')))
('not', ('and', ('p', 'a', 'x'), ('p', 'b', 'x')))
>>> tmp.repeat_bubble_until_finished(('not', ('p', ('and', 'a', 'b'), 'x')))
('and', ('not', ('p', 'a', 'x')), ('not', ('p', 'b', 'x')))

所以我想你必须在 recursive_bubble_ands_up 中构建一个“不”的特殊情况,或者在运行我的之前应用你的非处理函数,并将它插入到 repeat_bubble_until_finished 中的 recursive_bubble_ands_up 之前,这样他们'交替应用。

好吧,我现在该睡觉了。

【讨论】:

  • 我确实做了一些小改动:-首先,and_clauses 的集合应该颠倒过来,这样 is_atomic 就会短路。即:[(not is_atomic(subexpr) and 'and' in subexpr) for subexpr in expr] -其次,我在第一个 is_atomic 检查之后添加了一行,以确保主要短语不是“and”(或不是),因为它目前在以下情况下永远循环:repeat_bubble_until_finished(parse_expr("(p (and x y) (and a b))")) (即 if expr[0] in ('and', 'not'): return Expr ([recursive_bubble_ands_up(subexpr) for subexpr in expr]))
  • 但是再次感谢!这比我尝试的要优雅得多。 Python 非常漂亮。
  • 哦,好点子!是的,我忘记了重复的“和”案例,感谢您指出这一点!已经是午夜之后了。 ;) 无论如何,很高兴我给了你一些工作!写起来很有趣。 Python 非常漂亮,是的。
猜你喜欢
  • 1970-01-01
  • 2021-11-14
  • 2014-06-28
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
相关资源
最近更新 更多