Python - 查找嵌套列表中的所有列表

时间:2014-06-25 09:29:02

标签: python

我正在使用Python自己实现遗传编程(GP)。 GP旨在发展以LISP S表达式为代表的程序,以寻找解决问题的良好解决方案。

S表达式使用前缀表示法。例如:

(+ (- 1 2) (- 3 (/ 4 5)))

此表达式与中缀代数中的以下内容相同。

(1 - 2) + (3 - 4 / 5)

我正在使用Peter Norvig的LISP解释器(lispy)来解析和评估这些表达式。解析器将表达式转换为嵌套列表。例如,上述表达式表示为:

['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]

Peter Norvig的代码(从中删除了我不需要的运算符):

#lispy.py (Peter Norvig)

Symbol = str

def read(s):
    "Read a Scheme expression from a string."
    return read_from(tokenize(s))

parse = read

def tokenize(s):
    "Convert a string into a list of tokens."
    return s.replace('(',' ( ').replace(')',' ) ').split()

def read_from(tokens):
    "Read an expression from a sequence of tokens."
    if len(tokens) == 0:
        raise SyntaxError('unexpected EOF while reading')
    token = tokens.pop(0)
    if '(' == token:
        L = []
        while tokens[0] != ')':
            L.append(read_from(tokens))
        tokens.pop(0) # pop off ')'
        return L
    elif ')' == token:
        raise SyntaxError('unexpected )')
    else:
        return atom(token)

def atom(token):
    "Numbers become numbers; every other token is a symbol."
    try: return int(token)
    except ValueError:
        try: return float(token)
        except ValueError:
            return Symbol(token)

我现在需要编写函数来交配和改变表达式。这些遗传操作可能发生在列表中的任何位置。可以通过更改整个列表(在根)或通过更改其任何子表达式(列表)或终端(除运算符之外的列表元素)来突变上述表达式。因此,可以对以下任何一种进行突变:

['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]
['-', 1, 2]
['-', 3, ['/', 4, 5]]
['/', 4, 5]
1
2
3
4
5

因此,我认为下一步是编写一个以嵌套列表作为参数的函数,并返回其包含的所有列表,嵌套列表和终端(除运算符之外)的列表。然后我会随机选择生成的新列表中的一个元素并对其进行修改或将其与另一个表达式的组件交换。

我已经编写了下面的代码,但它没有按预期工作(参见底部的终端输出)。我对递归感觉不太舒服。任何人都可以帮助确定我做错了什么吗? (注意:全局变量仅用于尝试理解递归的工作原理)

from copy import deepcopy

global counter
counter = 0

def decompose_expr(list_in, operators, list_out=[], iter=0):
    global counter
    counter += 1
    print(str(counter) + ' list_out=' + str(list_out))
    if (len(list_in) != 0):
        if iter ==0:
            print(str(counter) + ' appending:' + str(list_in))
            list_out.append(deepcopy(list_in))
        print(str(counter) + ' list_out after appending:' + str(list_out))
        print(str(counter) + ' length of list_out after appending:' + str(len(list_out)))
        print(str(counter) + ' popping:' + str(list_in[0]))
        elem = list_in[0]
        if (type(elem) == list):
            print(str(counter) + ' appending:' + str(elem))
            list_out.append(deepcopy(elem))
        if (type(elem) != list and elem not in operators):
            print(str(counter) + ' appending:' + str(elem))
            list_out.append(elem)
        list_in.pop(0)
        print(str(counter) + ' recursion: list in is' + str(list_in) + ' list_out is ' + str(list_out) + '\n')
        iter += 1
        decompose_expr(list_in, operators, list_out)
        return list_out

operators = ['+', '-', '/', '*', '<', '>']

expr = '(+ (- 1 2) (- 3 (/ 4 5)))'

expr_representation = parse(expr)
print(expr_representation)
print(str(expr))
print('')

list_out = decompose_expr(expr_representation, operators)
print('\nThe result is:')
if list_out != None:
    for item in list_out:
        print(str(item))
else:
    print 'empty :('

我期望的结果是:

[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2], ['-', 3, ['/', 4, 5]], ['/', 4, 5], 1, 2, 3, 4 5]

但这是我得到的结果:

[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2], [['-', 3, ['/', 4, 5]]], ['-', 3, ['/', 4, 5]]]

这是终端输出:

['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]
(+ (- 1 2) (- 3 (/ 4 5)))

1 list_out=[]
1 appending:['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]
1 list_out after appending:[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]]
1 length of list_out after appending:1
1 popping:+
1 recursion: list in is[['-', 1, 2], ['-', 3, ['/', 4, 5]]] list_out is [['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]]

2 list_out=[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]]
2 appending:[['-', 1, 2], ['-', 3, ['/', 4, 5]]]
2 list_out after appending:[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]]]
2 length of list_out after appending:2
2 popping:['-', 1, 2]
2 appending:['-', 1, 2]
2 recursion: list in is[['-', 3, ['/', 4, 5]]] list_out is [['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2]]

3 list_out=[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2]]
3 appending:[['-', 3, ['/', 4, 5]]]
3 list_out after appending:[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2], [['-', 3, ['/', 4, 5]]]]
3 length of list_out after appending:4
3 popping:['-', 3, ['/', 4, 5]]
3 appending:['-', 3, ['/', 4, 5]]
3 recursion: list in is[] list_out is [['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2], [['-', 3, ['/', 4, 5]]], ['-', 3, ['/', 4, 5]]]

4 list_out=[['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]], [['-', 1, 2], ['-', 3, ['/', 4, 5]]], ['-', 1, 2], [['-', 3, ['/', 4, 5]]], ['-', 3, ['/', 4, 5]]]

The result is:
['+', ['-', 1, 2], ['-', 3, ['/', 4, 5]]]
[['-', 1, 2], ['-', 3, ['/', 4, 5]]]
['-', 1, 2]
[['-', 3, ['/', 4, 5]]]
['-', 3, ['/', 4, 5]]

谢谢,LC

1 个答案:

答案 0 :(得分:0)

我找到了这个解决方案:

def decompose_expr(list_in, operators, list_out=[], iter=0):

    if (len(list_in) != 0):
        if iter == 0:
            list_out.append(deepcopy(list_in))
        iter += 1
        if (type(list_in) == list):
            for elem in list_in:
                if elem not in operators:
                    list_out.append(deepcopy(elem))
                if (type(elem) == list):
                    decompose_expr(elem, operators, list_out, iter)
        else:
            if list_in not in operators:
                list_out.append(list_in)
    return list_out