查找文件夹中的所有文件并按部分文件名分组

Find all files in a folder and group by part of the filename

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

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

这是我的代码:

<?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 个结果,其中有两个重复项。 在开始循环之前,我找不到过滤结果的方法。 感谢任何帮助。

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

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

您可以将这两个循环结合起来,如果您之前已经输出了特定名称,则只需不输出任何内容即可。

这里有一条线:

$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() 匿名回调 returns 如果不是 '.''..' 的选项。 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>';

I cant find a way to filter the results before I start the loop.

scandir returns 包含给定目录中所有文件和目录名称的数组。

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

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

$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 
 */

$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。 始终 在输出时正确编码您的数据。