【问题标题】:Iterating through an arbitrarily nested array in python and changing matching values遍历python中的任意嵌套数组并更改匹配值
【发布时间】:2021-01-20 15:56:45
【问题描述】:

我有一个任意嵌套的值数组,如下所示:

['"multiply"', 'ALAssn ', ['ACmp ', ['Ge ', ['Var "n"'], ' ', ['Num 0']]], ['ALAssn ', ['ACmp ', ['Eq ', ['Var "p"'], ' ', ['Mul ', ['Var "n"'], ' ', ['Var "m"']]]]]

我需要尝试找出一种方法来解析数组中的每个值并对其进行格式化:

  1. 每个长度为 1 的数组被分成两个单独的值:

-- 示例: ['Var "n"'] 现在应该变成 ["Var", "n"]['Num 0'] 现在变成 ["Num", 0]

  1. 空列表值的所有实例都被删除。

-- 示例: ['Ge ', ['Var "n"'], ' ', ['Num 0']] 现在变为 ['Ge ', ['Var "n"'], ['Num 0']]

  1. 删除任何字符串中的空格。

-- 示例: 'Ge ' 现在变为 'Ge'

给定的 sn-p 是需要解析的更大字符串的一部分。我明白在高层次上需要做什么..ie:

  1. 一旦我得到一个长度为 1 的列表,list.split(" ") 将拆分为两个单独的元素,然后修剪 arr[1] 以去除多余的引号

  2. 如果el 是列表中每个元素的空字符串,list.remove(el)

  3. 遍历时检查每个元素的if isinstance(el, string),如果为真,el.replace(" ", "") 以消除空格。

我唯一的问题是遍历列表中的每个元素。我已经尝试递归和迭代地这样做,但到目前为止还无法破解它。

理想情况下,我会遍历每一个元素,然后在找到符合条件的元素后,将该元素设置为我想要对其进行的更改。这仅适用于第 1 点和第 3 点。

编辑:

非常感谢您提供的答案。我还有一个想要添加的内容。

假设我有一个像'Reads "a"' 这样的嵌套标识符作为数组的第一个值,并且有可能在同一级别具有像Write "a" 这样的附加标识符。这些也需要转换为["Read", "a"] 格式。请参阅下面大列表中的更改。我该怎么做呢?

['Read "a"', ['Add', ['Var', 'i'], ['Num', '1']]], 'Write "a"', ['Add', ['Var', 'i'], ['Num', '1']], ['Var', 't']]

这些值'Read''Write' 的意义在于,在遍历列表时,我们知道与该标识符对应的列表的下n 个元素的“类型”。我们基本上可以通过说它们是嵌套列表中唯一不会成为列表的值来区分它们。

例如: ['identifier', [], [], []]

假设已知identifier 类型包含3 个列表,firstsecondthird。例如,目标是读取标识符,然后将 firstsecondthird 存储为树中的节点。

【问题讨论】:

    标签: python arrays string recursion traversal


    【解决方案1】:

    这个问题似乎最容易解决,方法是用固定的项目构建一个新列表,而不是尝试修改现有的列表。这将允许您使用递归来处理嵌套,同时在每个列表的平坦部分上使用迭代。

    我会这样构造代码:

    def process(lst):
        if len(lst) == 1:                     # special case for one-element lists
            result = lst[0].split()
            result[1] = result[1].strip('"')  # strip quotation marks
            return result
    
        result = []
        for item in lst:
            if isinstance(item, list):
                result.append(process(item))  # recurse on nested lists
            else: # item is a string
                stripped = item.strip()       # remove leading and trailing whitespace
                if stripped:
                    result.append(stripped)   # keep only non-empty strings
        return result
    

    【讨论】:

    • 这个解决方案很容易理解,但可以调整它以适应编辑吗?
    • 编辑的特殊情况似乎未指定。是什么让'read "a"' 与众不同?空间?引号? 'read''write' 是硬编码的特殊情况吗?详细说明以及实现它的方法应该很简单。更糟糕的是,您可能需要一个简单的正则表达式测试。
    • 'Read 'Write 是嵌套列表中唯一不会成为列表本身的值。例如: ['identifier', [], [], []] 标识符的点是这样的,当遍历列表时,我们知道与该标识符对应的列表的下 n 个元素的“类型”。我也将此添加到问题中以使其更易于理解
    【解决方案2】:

    似乎您可以将 1 和 3 合并为一个操作:

    def sanitize(item):
        if isinstance(item, list):
            if len(item) == 1:
                item = item[0].split()
            return [output for i in item if (output := sanitize(i))]
        return item.strip('" ')  # Strips both '"' and ' '.
    
    
    item = ['"multiply"', 'ALAssn ', ['ACmp ', ['Ge ', ['Var "n"'], ' ', ['Num 0']]], ['ALAssn ', ['ACmp ', ['Eq ', ['Var "p"'], ' ', ['Mul ', ['Var "n"'], ' ', ['Var "m"']]]]]]
    sanitize(item)
    # Returns: ['multiply', 'ALAssn', ['ACmp', ['Ge', ['Var', 'n'], ['Num', '0']]], ['ALAssn', ['ACmp', ['Eq', ['Var', 'p'], ['Mul', ['Var', 'n'], ['Var', 'm']]]]]]
    

    【讨论】:

    • 这是一个干净的解决方案,但是您有什么想法可以修改它以处理我所做的编辑吗?
    • 最后一行 item.strip('" ') 是字符串值的全部内容。将该字符串转换为您需要的任何内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多