递归将项目添加到列表中 [英] Add an item into a list recursively

查看:137
本文介绍了递归将项目添加到列表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨.我想知道是否有一种方法可以将项目递归添加到列表中.该功能应该打印与fname匹配的文件的路径名.因此,fname是文件名,路径是文件所在的文件夹.如果路径文件夹中有文件夹,它将进入内部并查找fname文件.到目前为止,我已经能够找到所有文件.但是我不能递归地添加列表.

Hi. I was wondering if there is a way to add items into a list recursively. The function is supposed to print the path names of the file that matches with fname. So fname is the name of the file and the path is the folder in which the file is located. If there are folders inside the path folder it will go inside and look for the fname file. so far I am able to find all the files. But I am not able to append the list recursively.

def findAll(fname, path): 
 lst= []
 for item in os.listdir(path):
        n = os.path.join(path, item)
    try:
        if item == fname:
            lst.append(n)
    except:
        findAll(fname,n)
return lst

推荐答案

通常,我不会给出完整的解决方案,因为这听起来像是作业(这也是为什么我避免使用os.walk的原因),但是由于您有发布您的尝试,这是一种解释和解决方案:

Normally, I wouldn't give a full solution because this smells like homework (which is also why I'm avoiding os.walk), but since you have posted your attempt, here's an explanation and a solution:

一方面,每次调用findAll时,都要初始化lst.当然,您在最后返回了它,但是您对返回值不做任何事情,因此效果lst.append包含在递归中,因此在外部不可见.让我尝试绘制图表来解释这一点(使用一级递归):

For one thing, every time you call findAll, you initialize lst. Sure, you return it at the end, but you don't do anything with the return value, so the effect lst.append is contained within the recursion and is therefore not visible outside. Let me try to draw diagram to explain this (with one level of recursion):

+--------------------------------------------------+
|Outer Level:                                      |
|                                                  |
|`lst = []`                                        |
|found file f1 with name fname                     |
|`lst.append(f1)`                                  |
|+------------------------------------------------+|
||Inner Level                                     ||
||                                                ||
||`lst=[]`                                        ||
||found file f2 with name fname                   ||
||`lst.append(f2)`                                ||
||`return lst`                                    ||
|+------------------------------------------------+|
|a list is returned from recursive call,           |
|but not assigned to a variable.                   |
|Therefore, `lst` remains unchanged                |
+--------------------------------------------------+

有两种方法可以解决此问题:

There are a couple of ways by which you can fix this:

  1. lst移至findAll之外的范围(个人,这是我会做的事)
  2. 使用递归调用的返回值修改lst
  1. move lst to a scope outside findAll (personally, this is what I would do)
  2. use the return value from the recursive call to modify lst

lst移至findAll

move lst to a scope outside findAll

lst= []
def findAll(fname, path): 
    global lst
    for item in os.listdir(path):
        n = os.path.join(path, item)
        try: # really though, you don't need to use try/except here
            if item == fname:
                lst.append(n)
            else:
                findAll(fname,n)
        except:
            pass

findAll终止后,lst将包含您想要的值

After findAll has terminated, lst will contain the values you want

使用递归调用的返回值修改lst

use the return value from the recursive call to modify lst

def findAll(fname, path, answer=None):
    if answer == None:
        answer = []
    for item in os.listdir(path):
        n = os.path.join(path, item)
        try:
            if item == fname:
                answer += [n]
        except:
            findAll(fname,n, answer)
    return answer

希望这会有所帮助

PS:当然,非家庭作业的方法是使用os.walk:

PS: of course, the non-homework way to do this would be to use os.walk:

answer = []
def findAll(fname, dirpath):
    dirpath, dirnames, filenames = os.walk(dirpath)
    for filename in filenames:
        if filename == fname:
            answer.append(os.path.join(dirpath, filename))
    for dirname in dirnames:
        findAll(fname, os.path.join(dirpath, dirname))
# now, answer contains all the required filepaths

编辑:OP要求使用不使用全局变量的版本:

EDIT: OP asked for a version that doesn't use global variables:

def findAll(fname, root, answer=None):
    if answer == None:
        answer = []
     for entry in os.listdir(root):
         if os.path.isdir(os.path.join(root, entry)):
             answer += findAll(fname, os.path.join(root, entry))
         else:
             if entry == fname:
                 answer.append(os.path.join(root, entry))
     return answer

这篇关于递归将项目添加到列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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