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

时间:2023-01-14 10:27:34

I have a folder containing images like so:

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

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

I need to populate a drop-down list that contains only:

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

  • colorwaves
  • snow

this is my code:

这是我的代码:

<?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>";
}
?>

This will give me of course 4 results with two duplicates. I cant find a way to filter the results before I start the loop. Any help is appreciated.

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

3 个解决方案

#1


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

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

scandir returns an array with all the file and directory names within the given directory.

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

You want to filter this array (remove entries) that are duplicates of a changed name.

您希望筛选与更改名称重复的此数组(删除条目)。

You so far know how to change a name:

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

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

You also have an additional filter-condition that you don't want the dot-entries with the single and the double dots.

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

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

And in the end you need to filter the duplicates.

最后,您需要过滤重复项。

So let's bring this all together. First of all you have to obtain the directory listing:

所以让我们把这一切结合起来。首先,您必须获取目录列表:

$path = '../resources/banner/';

$files = scandir($path);

To filter the array, you can make use of array_filter:

要过滤数组,可以使用array_filter:

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

With this filter applied, the dot entries have been removed already. Next is to normalize the names. This can be done with mapping a callback function:

应用此过滤器后,点条目已被删除。接下来是规范化名称。这可以通过映射回调函数来完成:

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

With this mapping applied, the names of all files have been created.

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

Now you need to remove duplicate entries. This can be done with array_unique:

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

$files = array_unique($files);

After the array has been processed the way you wish, you only need to output it:

在按照您希望的方式处理数组后,您只需输出它:

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

Bringing this all together (Demo):

将这一切结合在一起(演示):

<?php
/**
 * @link http://*.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));
}

I hope this is helpful and demonstrates some programming tips:

我希望这有用,并演示了一些编程技巧:

  • separate your program logic into three main parts: input, processing and output.

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

  • when processing data, divide it into multiple small steps so that each step does on thing and does it right. you can then build your program step by step and always try it in the meantime if it still works.

    在处理数据时,将其分成多个小步骤,以便每个步骤对事物进行操作并正确执行。然后你可以一步一步地构建你的程序,并且如果它仍然有效的话,总是在此期间尝试它。

  • PHP has many array functions. If you use arrays, use them. The PHP manual discusses each of them, I've shown three basic ones: array_filter, array_map and array_unique.

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

  • callback functions allow you to extend PHP core functionality (or: other persons code) with your own code. there is no need to write all from scratch. look for functionality to re-use.

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

  • when you output HTML, you have to encode your data properly (here: as HTML). As you can't control the names in the directory listing, HTML could be otherwise injected. Always encode your data properly on output.

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

#2


Keep track of what you've found, and only do the output portion AFTER you've processed everything:

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

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

You could combine both loops, and simply NOT output anything if you've already previously output a particular name.

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

#3


Here's a one-liner:

这是一个单行:

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

The array_map() anonymous callback returns the option if it's not '.' or '..'. The array_unique() removes duplicates. The array_filter() removes empties. The array_values, which is optional, resets the array keys.

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

EDIT: Here's a one-liner with the scandir included and the select element included:

编辑:这是一个包括scandir和选择元素的单线程:

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

#1


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

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

scandir returns an array with all the file and directory names within the given directory.

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

You want to filter this array (remove entries) that are duplicates of a changed name.

您希望筛选与更改名称重复的此数组(删除条目)。

You so far know how to change a name:

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

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

You also have an additional filter-condition that you don't want the dot-entries with the single and the double dots.

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

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

And in the end you need to filter the duplicates.

最后,您需要过滤重复项。

So let's bring this all together. First of all you have to obtain the directory listing:

所以让我们把这一切结合起来。首先,您必须获取目录列表:

$path = '../resources/banner/';

$files = scandir($path);

To filter the array, you can make use of array_filter:

要过滤数组,可以使用array_filter:

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

With this filter applied, the dot entries have been removed already. Next is to normalize the names. This can be done with mapping a callback function:

应用此过滤器后,点条目已被删除。接下来是规范化名称。这可以通过映射回调函数来完成:

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

With this mapping applied, the names of all files have been created.

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

Now you need to remove duplicate entries. This can be done with array_unique:

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

$files = array_unique($files);

After the array has been processed the way you wish, you only need to output it:

在按照您希望的方式处理数组后,您只需输出它:

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

Bringing this all together (Demo):

将这一切结合在一起(演示):

<?php
/**
 * @link http://*.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));
}

I hope this is helpful and demonstrates some programming tips:

我希望这有用,并演示了一些编程技巧:

  • separate your program logic into three main parts: input, processing and output.

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

  • when processing data, divide it into multiple small steps so that each step does on thing and does it right. you can then build your program step by step and always try it in the meantime if it still works.

    在处理数据时,将其分成多个小步骤,以便每个步骤对事物进行操作并正确执行。然后你可以一步一步地构建你的程序,并且如果它仍然有效的话,总是在此期间尝试它。

  • PHP has many array functions. If you use arrays, use them. The PHP manual discusses each of them, I've shown three basic ones: array_filter, array_map and array_unique.

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

  • callback functions allow you to extend PHP core functionality (or: other persons code) with your own code. there is no need to write all from scratch. look for functionality to re-use.

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

  • when you output HTML, you have to encode your data properly (here: as HTML). As you can't control the names in the directory listing, HTML could be otherwise injected. Always encode your data properly on output.

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

#2


Keep track of what you've found, and only do the output portion AFTER you've processed everything:

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

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

You could combine both loops, and simply NOT output anything if you've already previously output a particular name.

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

#3


Here's a one-liner:

这是一个单行:

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

The array_map() anonymous callback returns the option if it's not '.' or '..'. The array_unique() removes duplicates. The array_filter() removes empties. The array_values, which is optional, resets the array keys.

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

EDIT: Here's a one-liner with the scandir included and the select element included:

编辑:这是一个包括scandir和选择元素的单线程:

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