如何从文件夹树中快速选择随机文件?
How to quickly pick a random file from a folder-tree?
我正在尝试从文件夹树中选择一个随机文件,从固定路径开始,并在所有子文件夹(或所选文件夹本身(中递归"搜索"。
我的想法是:制作文件列表,计算文件数量,在此范围内选择一个随机数,然后在该索引处选择文件。
这是我的代码:
// create list of all files
std::vector<std::string> paths;
for (const auto &entry : std::filesystem::recursive_directory_iterator(mPathDirectory)) {
if (!std::filesystem::is_directory(entry)) {
paths.push_back(entry.path().string());
}
}
// pick random file
size_t numberOfFiles = paths.size();
int indexRandomFile = (int)round(rescale(random::uniform(), 0.0, 1.0, 0, numberOfFiles - 1));
return paths[indexRandomFile];
同样使用O3
,考虑到我有大量的文件列表并且我在"音频"应用程序中(应该更快(,它非常慢。
你有什么更聪明的想法吗?像O(1(这样的东西?:P
使用储层采样技术可以通过这种方式随机统一选择文件。对于每个文件,以 1/N 的几率选择它,其中 N 是到目前为止找到的文件数,包括刚刚找到的文件。然后,随机文件是以这种方式选择的最后一个文件。
另请参阅此问题,了解从文本文件中随机选择一行的类似任务;通常,只要事先不知道要选择的项目数量,就适用储层采样。
下面解释了储层取样的工作原理:
- 将 N 设置为 1。
- 将"选择文件"设置为空。
- 对于每个文件:
- 如果
random::uniform() < 1.0 / N
,请将"选择文件"设置为文件名。 - 将 1 加到 N。
- 如果
现在,ChosenFile是随机选择的文件名。
根据您问题中的代码,以下是如何实施储层采样。请注意,列表中不再存储任何文件。另请注意,此代码未经测试。
// store randomly chosen file
std::string path;
size_t n = 1;
for (const auto &entry: std::filesystem::recursive_directory_iterator(mPathDirectory)) {
if (!std::filesystem::is_directory(entry)) {
if (random::uniform() < 1.0 / n) {
path = entry.path().string();
}
n++;
}
}
return path;
如果您对文件夹结构一无所知,则必须递归以找出有多少项。没有O(1(解决方案。
但是一个"应用程序"只需要感觉快速,也就是说,通常只有对响应能力的感知才是重要的。为此,在第一次启动时,您可以使用启发式方法,例如以一定的概率递归到某些子文件夹中,直到找到文件。它不会是均匀随机的,但从用户的角度来看,它会相对任意地选择。
同时,您可以真正递归到文件夹中并建立缓存,而最初选择的文件已经在播放。
相关文章:
- 用C++快速读写文件
- 防止在C++中选择错误文件时提升 xml 解析器崩溃
- 限制用户可以在 QFileDialog 中选择的文件数量
- 如何从目录迭代器中选择特定文件并进行比较
- 选择随机字符串数组的排序
- 快速计算 CSV 文件 C++ 中的行数
- 如何从文件夹树中快速选择随机文件?
- 从长(且合理)稀疏向量中选择随机元素的最有效方法是什么?
- 最小 kth 用于快速选择算法
- 执行C 代码时快速频繁的文件访问
- 如何快速保存大文件中的小更改
- 阻止特定的随机文件夹
- 将文件上传到随机文件夹中
- 为什么我的中位数快速选择算法segfault
- 快速选择算法因元素重复而失败
- 回溯到sudoku求解每次选择随机单元和随机值的逻辑
- 将数据从C++Vector快速写入文本文件
- 如何有效地从std::集中选择随机元素
- 随机文件写入
- 使用c++从.dat文件中选择“随机行”