【问题标题】:Find all files in a folder and group by part of the filename查找文件夹中的所有文件并按文件名的一部分进行分组
【发布时间】:2015-05-06 17:02:27
【问题描述】:

我有一个包含如下图像的文件夹:

  • colorwaves-1.png
  • colorwaves-2.png
  • snow-1.png
  • snow-2.png

我需要填充一个下拉列表,其中仅包含:

  • 色波

这是我的代码:

<?php
$files = scandir('../resources/banner/');
foreach ($files as $file)
  if ($file != "." && $file != ".."){
  $x = array_shift(explode('-', $file));  //remove everything after "-"
  echo "<option value='".$x."'>".$x."</option>";
}
?>

这当然会给我 4 个结果,其中两个重复。 在开始循环之前,我找不到过滤结果的方法。 任何帮助表示赞赏。

【问题讨论】:

    标签: php foreach scandir


    【解决方案1】:

    在开始循环之前我找不到过滤结果的方法。

    scandir 返回一个包含给定目录中所有文件和目录名称的数组。

    您想要过滤与更改名称重复的数组(删除条目)。

    到目前为止,您知道如何更改名称:

    $name = strtok($file, '-');
    

    您还有一个额外的过滤条件,您不希望带有单点和双点的点条目。

    ($file != "." && $file != "..")
    

    最后你需要过滤重复项。

    所以让我们把这一切放在一起。首先你要获取目录列表:

    $path = '../resources/banner/';
    
    $files = scandir($path);
    

    要过滤数组,可以使用array_filter

    $files = array_filter($files, function($file) {
        return ($file != "." && $file != "..");
    });
    

    应用此过滤器后,点条目已被删除。接下来是规范化名称。这可以通过mapping a callback function 来完成:

    $files = array_map(function($file) {
        return strtok($file, '-');
    }, $files);
    

    应用此映射后,所有文件的名称都已创建。

    现在您需要删除重复的条目。这可以通过array_unique 来完成:

    $files = array_unique($files);
    

    数组按照你想要的方式处理后,你只需要输出它:

    foreach ($files as $file) {
        printf("<option value='%1\$s'>%1\$s</option>", htmlspecialchars($file));
    }
    

    把这一切放在一起 (Demo):

    <?php
    /**
     * @link http://stackoverflow.com/a/30092161/367456
     */
    
    $path = '.';
    
    $files = scandir($path);
    
    $files = array_filter($files, function($file) {
        return ($file != "." && $file != "..");
    });
    
    $files = array_map(function($file) {
        return strtok($file, '-');
    }, $files);
    
    $files = array_unique($files);
    
    foreach ($files as $file) {
        printf("<option value='%1\$s'>%1\$s</option>\n", htmlspecialchars($file));
    }
    

    我希望这会有所帮助并演示一些编程技巧:

    • 将您的程序逻辑分为三个主要部分:输入、处理和输出。

    • 在处理数据时,将其分成多个小步骤,以便每个步骤都在做事并做对。然后,您可以逐步构建您的程序,如果它仍然有效,请随时尝试。

    • PHP 有许多数组函数。如果您使用数组,请使用它们。 PHP 手册讨论了它们中的每一个,我展示了三个基本的:array_filter、array_map 和 array_unique。

    • 回调函数允许您使用自己的代码扩展 PHP 核心功能(或:其他人的代码)。没有必要从头开始写。寻找可重复使用的功能。

    • 当您输出 HTML 时,您必须正确编码您的数据(这里:作为 HTML)。由于您无法控制目录列表中的名称,因此可能会注入 HTML。 始终在输出时正确编码您的数据。

    【讨论】:

    • 非常感谢您为此付出的时间。这对我来说很有意义并且有效。非常感谢。
    【解决方案2】:

    跟踪您发现的内容,仅在处理完所有内容后执行输出部分:

    $data = array();
    foreach(...) {
        $text = function_to_extract_relevant_filename_portion();
        $data[$text] = true;
    }
    $file_name_parts = array_keys($data);
    ... output filename parts here ...
    

    您可以组合这两个循环,如果您之前已经输出了特定名称,则根本不输出任何内容。

    【讨论】:

      【解决方案3】:

      这是一个单行:

      $files = array_values(array_filter(array_unique(array_map(function($a){ if(!in_array($a, array('.','..'))){ $a = explode('-', $a); return "<option value='".$a[0]."'>".$a[0]."</option>"; }}, $files))));
      

      如果不是'.''..'array_map() 匿名回调将返回选项。 array_unique() 删除重复项。 array_filter() 删除空。 array_values 是可选的,用于重置数组键。

      编辑: 这是一个包含 scandir 和 select 元素的单行代码:

      return '<select>'.implode(' ', array_values(array_filter(array_unique(array_map(function($a){ if(!in_array($a, array('.','..'))){ $a = explode('-', $a); return "<option value='".$a[0]."'>".$a[0]."</option>"; }}, scandir('../resources/banner/')))))).'</select>';
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-26
        • 2021-10-30
        • 1970-01-01
        • 1970-01-01
        • 2021-05-29
        • 2021-10-30
        • 1970-01-01
        相关资源
        最近更新 更多