#include <iostream>
#include <vector>
#include <filesystem>
#include <regex>
#include <unordered_map>
struct PathList {
std::vector<std::filesystem::path> directories;
std::vector<std::filesystem::path> files;
};
// 指定したパス内のファイル一覧を取得
PathList GetFileList(const std::filesystem::path& _path) {
PathList result;
if (!std::filesystem::exists(_path) || !std::filesystem::is_directory(_path)) {
return result; // 存在しない場合は空を返す
}
for (const auto& entry : std::filesystem::directory_iterator(_path)) {
if (entry.is_directory()) {
result.directories.push_back(entry.path());
}
else if (entry.is_regular_file()) {
result.files.push_back(entry.path());
}
}
return result;
}
// パスのファイル名からIDを取り出し、pair<size_t, path> の配列で返す
std::vector<std::pair<size_t, std::filesystem::path>>
GetFileIncdies(const std::vector<std::filesystem::path>& pathlist,
const std::regex& pattern,
std::vector<std::filesystem::path>* excep)
{
std::vector<std::pair<size_t, std::filesystem::path>> result;
for (const auto& p : pathlist) {
const std::string name = p.filename().string();
std::smatch m;
if (std::regex_search(name, m, pattern)) {
// パターンにマッチしたかどうか
bool ok = false;
size_t idx = 0;
for (size_t i = 1; i < m.size(); ++i) {
const std::string s = m[i].str();
if (s.empty()) continue;
// すべて数字かを判定
const bool all_digits = std::all_of(s.begin(), s.end(),
[](unsigned char c) { return std::isdigit(c) != 0; });
if (!all_digits) continue;
try {
idx = static_cast<size_t>(std::stoull(s));
ok = true;
break;
}
catch (...) {
// stoull 失敗時は次のキャプチャを試す
}
}
if (ok) {
result.emplace_back(idx, p);
}
else if (excep) {
excep->push_back(p);
}
}
else {
if (excep) excep->push_back(p);
}
}
// インデックス昇順、同値ならパスの辞書順
std::sort(result.begin(), result.end(),
[](const auto& a, const auto& b) {
if (a.first != b.first) return a.first < b.first;
return a.second < b.second;
});
return result;
}
template<typename Tuple,typename Pair,int Index>
std::unordered_map<size_t, Tuple> CreateDataSetList(std::unordered_map<size_t, Tuple>& datamap,std::vector<Tuple>& datasets, std::vector<Pair>& pairs) {
for (const auto& p : pairs) {
size_t idx = p.first;
const auto& path = p.second;
auto& tupleitem = datamap[idx];
std::get<Index>(tupleitem) = path; // Index番目にパスをセット
}
return datamap;
}
// マップをIDでソートしたものを返す
template<typename Tuple>
std::vector<std::pair<size_t, Tuple>> SortByID(const std::unordered_map<size_t, Tuple>& byidmap) {
std::vector<std::pair<size_t, Tuple>> sorted;
sorted.reserve(byidmap.size());
for (const auto& kv : byidmap) {
sorted.emplace_back(kv.first, kv.second);
}
std::sort(sorted.begin(), sorted.end(),
[](const auto& lhs, const auto& rhs) {
return lhs.first < rhs.first; // size_tキーで昇順
});
return sorted;
}
using Tuple = std::tuple<std::filesystem::path, std::filesystem::path, std::filesystem::path>;
using Pair = std::pair<size_t, std::filesystem::path>;
// パスとパターンからファイル一覧を作成し、インデックスとパスのペアを返す関数
std::vector<std::pair<size_t, std::filesystem::path> > GetFiles(const std::filesystem::path& path,std::regex pattern){
PathList fileList = GetFileList(path);
std::vector<std::pair<size_t, std::filesystem::path> > flist;
flist = GetFileIncdies(fileList.files, pattern, nullptr);
return flist;
}
int main()
{
std::vector< Tuple > dataSetList;
std::vector<Pair > list_1 = GetFiles("C:\\test\\tmp\\txt", std::regex(R"(新規 テキスト000_(\d+)\.txt)") );
std::vector<Pair > list_2 = GetFiles("C:\\test\\tmp\\doc", std::regex(R"(doc_000_(\d+)\.doc)") );
std::unordered_map<size_t, Tuple> byidmap;
CreateDataSetList<Tuple, Pair, 0>(byidmap, dataSetList, list_1);
CreateDataSetList<Tuple, Pair, 1>(byidmap, dataSetList, list_2);
std::vector<std::pair<size_t, Tuple>> sorted = SortByID(byidmap);
for(const auto& b : sorted) {
std::cout << "ID: " << b.first << " " << std::get<0>(b.second).filename() << " " << std::get<1>(b.second).filename() << " " << std::get<2>(b.second) << "\n";
}
}