查找文件夹中的所有文件,并按文件名的一部分进行分组

时间:2015-05-06 17:02:28

标签: php foreach scandir

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

  • colorwaves-1.png
  • colorwaves-2.png
  • 雪1.png
  • 雪2.png

我需要填充仅包含以下内容的下拉列表:

  • colorwaves

这是我的代码:

<?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个结果,两个重复。 在开始循环之前,我无法找到过滤结果的方法。 任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

跟踪您找到的内容,并且只在您处理完所有内容后执行输出部分:

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

你可以组合两个循环,如果你之前已经输出了一个特定的名字,就不输出任何东西。

答案 1 :(得分:1)

这是一个单行:

$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>';

答案 2 :(得分: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。 始终在输出上正确编码您的数据。