从深层嵌套列表/元组中提取元素的递归函数 [英] recursive function for extract elements from deep nested lists/tuples

查看:33
本文介绍了从深层嵌套列表/元组中提取元素的递归函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个从深层嵌套的元组和列表中提取元素的函数,比如我有这样的东西

I want to write a function that extracts elements from deep nested tuples and lists, say I have something like this

l = ('THIS', [('THAT', ['a', 'b']), 'c', ('THAT', ['d', 'e', 'f'])])

我想要一个没有这个"和那个"的平面列表:

And I want a flat list without 'THIS' and 'THAT':

list = ['a', 'b', 'c', 'd', 'e', 'f']

这是我目前所拥有的:

def extract(List):
    global terms
    terms = []
    for i in word:
        if type(i) is not str:
            extract(i)
        else:
            if i is not "THIS" and i is not "THAT":
                terms.append(i)
    return terms

但我一直得到 list = ['d', 'e', 'f'],看起来 terms = [] 在循环后再次设置到 'c'.

But I keep getting list = ['d', 'e', 'f'], it looks like the terms = [] is set again after looping to 'c'.

推荐答案

你是在函数顶部做terms = [],所以当然每次递归调用函数时,你又在这样做了terms=[].

You're doing terms = [] at the top of the function, so of course every time you recursively call the function, you're doing that terms=[] again.

最快的解决方案是编写一个简单的包装器:

The quickest solution is to write a simple wrapper:

def _extract(List):
    global terms
    for i in word:
        if type(i) is not str:
            _extract(i)
        else:
            if i is not "THIS" and i is not "THAT":
                terms.append(i)
    return terms

def extract(List):
    global terms
    terms = []
    return _extract(List)

<小时>

还有一点:你不应该使用 is 来测试字符串是否相等(除非在非常非常特殊的情况下).这将测试它们内存中的相同字符串对象.它会碰巧在这里工作,至少在 CPython 中(因为 "THIS" 两个字符串都是同一个模块中的常量——即使它们不是,他们也会得到 interned)——但这不是你想要依赖的东西.使用 ==,它测试它们是否表示相同的字符串,无论它们是否实际上是相同的对象.


One more thing: You shouldn't use is to test for string equality (except in very, very special cases). That tests that they're the same string object in memory. It will happen to work here, at least in CPython (because both "THIS" strings are constants in the same module—and even if they weren't, they'd get interned)—but that's not something you want to rely on. Use ==, which tests that they both mean the same string, whether or not they're actually the identical object.

测试类型的身份更有用一点,但通常仍然不是您想要的.事实上,您通常甚至不想测试类型是否相等.您通常不会拥有 str 的子类——但如果有,您可能希望将它们视为 str(因为这是子类型化的全部意义所在).这对于您更频繁地进行子类化的类型更为重要.

Testing types for identity is useful a little more often, but still not usually what you want. In fact, you usually don't even want to test types for equality. You don't often have subclasses of str—but if you did, you'd probably want to treat them as str (since that's the whole point of subtyping). And this is even more important for types that you do subclass from more often.

如果您不完全理解所有这些,简单的指导原则是永远不要使用 is,除非您知道自己有充分的理由这样做.

If you don't completely understand all of that, the simple guideline is to just never use is unless you know you have a good reason to.

所以,改变这个:

if i is not "THIS" and i is not "THAT":

…到这个:

if i != "THIS" and i != "THAT":

或者,也许更好(如果你有四个字符串来检查而不是两个,肯定会更好),使用集合成员测试而不是将多个测试放在一起:

Or, maybe even better (definitely better if you had, say, four strings to check instead of two), use a set membership test instead of anding together multiple tests:

if i not in {"THIS", "THAT"}:

同样,改变这个:

if type(i) is not str:

…到这个:

if not isinstance(i, str):

<小时>

但是,虽然我们在这里都是函数式的,为什么不使用闭包来消除全局呢?


But while we're being all functional here, why not use a closure to eliminate the global?

def extract(List)
    terms = []
    def _extract(List):
        nonlocal terms
        for i in word:
            if not isinstance(i, str):
                _extract(i)
            else:
                if i not in {"THIS", "THAT"}:
                    terms.append(i)
        return terms
    return _extract(List)

这不是我解决这个问题的方式(wim 的回答可能是我会做的,如果给出这个规范并被告知用递归解决它),但这具有保留现有设计(以及大部分实现)的精神的优点.

This isn't the way I'd solve this problem (wim's answer is probably what I'd do if given this spec and told to solve it with recursion), but this has the virtue of preserving the spirit of (and most of the implementation of) your existing design.

这篇关于从深层嵌套列表/元组中提取元素的递归函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆