简体   繁体   English

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

[英]Python - find all lists in a nested list

I am working on my own implementation of genetic programming (GP) in Python. 我正在用Python自己实现基因编程(GP)。 GP aims at evolving programs, represented as LISP S-expressions, to search for a good solution to a problem. GP致力于开发以LISP S表达式表示的程序,以寻求解决问题的好的方法。

S-expressions use prefix notation. S表达式使用前缀表示法。 For instance: 例如:

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

This expression is equivalent to the following in infix algebra. 该表达式与infix代数中的以下表达式等效。

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

I am using Peter Norvig's LISP interpreter (lispy) to parse and evaluate these expressions. 我正在使用Peter Norvig的LISP解释器(lispy)来解析和评估这些表达式。 The parser converts expressions to nested lists. 解析器将表达式转换为嵌套列表。 The above expression would for instance be represented as: 上面的表达式将例如表示为:

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

Peter Norvig's code (from which I removed operators that I do not need): 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)

I now need to write functions to mate and mutate expressions. 现在,我需要编写函数以匹配和变异表达式。 These genetic operations may occur at any position in the list. 这些遗传操作可能发生在列表中的任何位置。 The above expression could be mutated by changing either the whole list (at root), or by changing any of its sub-expressions (lists) or terminals (list element other than the operator). 可以通过更改整个列表(从根开始)或更改其任何子表达式(列表)或终端(除运算符之外的列表元素)来使上述表达式发生突变。 The mutation could therefore be performed on any of the following: 因此,可以对以下任何一种进行突变:

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

I therefore think the next step to write a function that takes a nested list as an argument and returns a list of all lists, nested lists and terminals (other than operators) that its contains. 因此,我认为下一步是编写一个将嵌套列表作为参数并返回包含它的所有列表,嵌套列表和终端(运算符除外)的列表的函数。 I would then randomly pick an element of the resulting new list and mutate it or swap it with the component of another expression. 然后,我将随机选择结果新列表中的一个元素并将其变异或与另一个表达式的组件交换。

I have written the code below, but it does not work as expected (see terminal output at the bottom). 我已经在下面编写了代码,但是它没有按预期工作(请参阅底部的终端输出)。 I am not very comfortable with recursion yet. 我对递归还不太满意。 Could anyone help pinpoint what I am doing wrong? 谁能帮我找出我做错了什么? (Note: the global variable is only for the purpose of trying to understand how recursion works) (注意:全局变量仅用于尝试了解递归的工作方式)

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 :('

The result I expect is: 我期望的结果是:

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

But here is the result I get: 但是,这是我得到的结果:

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

And here is the terminal output: 这是终端输出:

['+', ['-', 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]]

Thanks, LC 谢谢LC

I have found this solution: 我找到了这个解决方案:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM