代码之家  ›  专栏  ›  技术社区  ›  Decent Dabbler

构造迭代器

  •  0
  • Decent Dabbler  · 技术社区  · 15 年前

    假设您想要构造一个迭代器来吐出文件对象。您通常向这种迭代器的构造函数提供什么类型的数据?

    • 预先构造的文件对象数组,或
    • 只需原始数据(例如多维数组),并让迭代器在遍历时动态创建文件对象?

    编辑:
    虽然我的问题实际上是尽可能的笼统,但我的例子似乎对笼统的处理有点宽泛,所以我将详细阐述。我所说的文件对象实际上是数据库中的文件引用。见下表:

    folder
    | id | folderId | name             |
    ------------------------------------
    |  1 |     null | downloads        |
    
    file
    | id | folderId | name             |
    ------------------------------------
    |  1 |        1 | instructions.pdf |
    

    它们引用文件系统上的实际文件夹和文件。

    现在,我创建了一个文件管理器对象。这将能够返回文件夹和文件的列表。例如:

    FileManager::listFiles( Folder $folder );
    

    …将从数据库返回文件对象的迭代器(或者,想到它,更确切地说,是文件引用对象)。

    所以我的问题归结为: 如果FileManager对象在listfiles()中构造迭代器,您会这样做吗(伪代码):

    listFiles( Folder $folder )
    {
        // let's assume the following returns an multidimensional array of rows
        $filesData = $db->fetch( $sqlForFetchingFilesFromFolder );
        // let the Iterator take care of constructing the FileReference objects with each iteration
        return FileIterator( $filesData );
    
    }
    

    或(伪代码):

    listFiles( Folder $folder )
    {
        // let's assume the following returns an multidimensional array of rows
        $filesData = $db->fetch( $sqlForFetchingFilesFromFolder );
        $files = array();
        for each( $filesData as $fileData )
        {
            $files.push ( new FileReference( $fileData ) );
        }
        // provide the Iterator with precomposed FileReference objects
        return FileIterator( $files );
    
    }
    

    希望这能澄清一点。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Jon Skeet    15 年前

    你的“文件”对象是什么?打开文件的句柄,或者可以依次打开的文件系统路径的表示?

    一次打开所有文件通常是一个坏主意——毕竟,使用迭代器的一部分目的是一次只访问一个对象。迭代器可以一次生成一个打开的文件,并让调用者负责关闭它,尽管这可能有点奇怪。

    老实说,您的需求并不清楚——根据我的经验,大多数生成一系列文件的迭代器都使用类似 Directory.GetFiles(pattern) -你根本不把原始数据传给他们,而是把他们用来寻找数据的东西传给他们。 为你 .

    你想知道什么并不明显,感觉你想问一个一般性的问题,但是你没有提供足够的信息让我们给你建议。就像问,“我想用字符串还是整数?”没有任何上下文。

    编辑:我可能会推 全部的 把这个逻辑转化为 FileIterator ,个人。否则,很难看到它真正提供了什么价值。在C或python这样的语言中,首先不需要单独的类——您只需要使用一些描述的生成器。从这个意义上说,这个问题不是语言不可知论:(

        2
  •  1
  •   Dario    15 年前

    您的迭代器应该做什么?将数据写入文件?创建它们?

    迭代器是 迭代 通过数据,这意味着 提供 顺序数据以一致的方式,而不是 突变 他们。

        3
  •  1
  •   djna    15 年前

    我觉得这个问题不清楚。

    我们说的是迭代器还是工厂?

    对我来说,迭代器正在对预先存在的 东西 并允许调用者处理每个 事情 反过来。

    当您说“spits out”时,您的意思是允许客户机使用一组预先存在的文件中的一个文件,还是说您正在迭代一些数据,并打算将这些数据存储在要生成的文件中。如果我们正在生成,那么我们就有了一个文件工厂。

    我猜你打算在文件系统中处理一些文件。我认为您的迭代器类似于一个目录,它可以为您提供它知道的下一个文件。所以我通过传递足够的数据来构造“driectory”,让它知道您的意思是什么文件(可能只是一个操作系统路径,可能是某种“查找”表达式,一个类似于ftp的引用列表等),并期望它在我迭代时给我下一个文件。

    ——问题澄清后更新

    我认为这里的关键问题是什么时候应该打开单个文件。迭代器本身将合理地返回与打开的文件句柄相对应的文件对象,然后调用方就可以处理该文件。但实际上,迭代器应该针对 列表 预先打开的文件或 列表 对于文件引用,使用作为迭代器next()打开的文件。

    我认为我们应该做后者,因为有一个打开的文件会有开销,因此我们应该只在需要的时候打开这些文件。

    这又引出了另一个问题:谁关闭了文件?我们负担不起把它们全部打开。也许迭代器应该在调用next()时关闭每个文件。这意味着迭代器本身需要一个close()方法来清理当前打开的文件。另外,我们需要明确地记录客户的责任是结案。

        4
  •  0
  •   stakx - no longer contributing Saravana Kumar    15 年前

    这取决于你需要什么。例如,您可以有:

    • 要循环访问的文件名的集合/列表;
    • 要循环访问的目录的名称;
    • 迭代器可以自行决定要返回哪些文件;

    您可以设计一个底层类,例如 FilenameCollection Directory 它有一个方法,该方法为这种类型的对象返回适当的迭代器(即迭代器“工厂方法”),而不要求将参数传递给迭代器的构造函数。