查找文件夹中的所有文件并按部分文件名分组
Find all files in a folder and group by part of the filename
我有一个包含如下图片的文件夹:
- colorwaves-1.png
- colorwaves-2.png
- 雪-1.png
- 雪-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 个结果,其中有两个重复项。
在开始循环之前,我找不到过滤结果的方法。
感谢任何帮助。
跟踪您找到的内容,并且仅在处理完所有内容后才执行输出部分:
$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。 始终 在输出时正确编码您的数据。
我有一个包含如下图片的文件夹:
- colorwaves-1.png
- colorwaves-2.png
- 雪-1.png
- 雪-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 个结果,其中有两个重复项。 在开始循环之前,我找不到过滤结果的方法。 感谢任何帮助。
跟踪您找到的内容,并且仅在处理完所有内容后才执行输出部分:
$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。 始终 在输出时正确编码您的数据。