std::transform 如何不返回(而不抛出),只是跳过?
我想显示文件夹内容(没有任何文件夹系统),因此有一个 std::set
,其中包含 std::strings
以及一些给定的路径我们想要像普通文件系统一样搜索某些目录的文件夹内容。因此,有了一组:
set<string> demo_set;
demo_set.insert("file1");
demo_set.insert("file2");
demo_set.insert("folder/file1");
demo_set.insert("folder/file2");
demo_set.insert("folder/folder/file1");
demo_set.insert("folder/folder/file2");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
demo_set.insert("bin/obj/Debug/vc100.idb");
demo_set.insert("bin/obj/Debug/vc100.pdb");
和搜索字符串 "bin/obj/Debug/"
我们想要获得 3 个项目 - 文件夹,2 个文件:
CloudServerPrototype/
vc100.idb
vc100.pdb
但我们也得到一个空行。如何不获取它以及如何在未找到项目的情况下抛出错误?
整个代码:
#include <iostream>
#include <algorithm>
#include <set>
#include <string>
#include <iterator>
using namespace std;
struct get_pertinent_part
{
const std::string given_string;
get_pertinent_part(const std::string& s)
:given_string(s)
{
}
std::string operator()(const std::string& s)
{
std::string::size_type first = 0;
if (s.find(given_string) == 0)
{
first = given_string.length();
}
else
{
return "";
}
std::string::size_type count = std::string::npos;
std::string::size_type pos = s.find_last_of("/");
if (pos != std::string::npos && pos > first)
{
count = pos + 1 - first;
}
return s.substr(first, count);
}
};
void directory_listning_without_directories_demo()
{
set<string> output;
set<string> demo_set;
demo_set.insert("file1");
demo_set.insert("file2");
demo_set.insert("folder/file1");
demo_set.insert("folder/file2");
demo_set.insert("folder/folder/file1");
demo_set.insert("folder/folder/file2");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
demo_set.insert("bin/obj/Debug/vc100.idb");
demo_set.insert("bin/obj/Debug/vc100.pdb");
std::transform(demo_set.begin(),
demo_set.end(),
std::inserter(output, output.end()),
get_pertinent_part("bin/obj/Debug/"));
std::copy(output.begin(),
output.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
int main()
{
directory_listning_without_directories_demo();
cin.get();
return 0;
}
基于 这个很好的答案。
I want to display folder contents displaying (not having any folder system) So Having a std::set<string_file_names>
with std::strings
in it and some given path to some dir we want to search for folder contents as in normal fs. so having set of:
set<string> demo_set;
demo_set.insert("file1");
demo_set.insert("file2");
demo_set.insert("folder/file1");
demo_set.insert("folder/file2");
demo_set.insert("folder/folder/file1");
demo_set.insert("folder/folder/file2");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
demo_set.insert("bin/obj/Debug/vc100.idb");
demo_set.insert("bin/obj/Debug/vc100.pdb");
and search string "bin/obj/Debug/"
we want to get 3 Items - folder, 2 files:
CloudServerPrototype/
vc100.idb
vc100.pdb
But we get also an empty line. How to not get it and how to throw an error in case of non items found?
Entire code:
#include <iostream>
#include <algorithm>
#include <set>
#include <string>
#include <iterator>
using namespace std;
struct get_pertinent_part
{
const std::string given_string;
get_pertinent_part(const std::string& s)
:given_string(s)
{
}
std::string operator()(const std::string& s)
{
std::string::size_type first = 0;
if (s.find(given_string) == 0)
{
first = given_string.length();
}
else
{
return "";
}
std::string::size_type count = std::string::npos;
std::string::size_type pos = s.find_last_of("/");
if (pos != std::string::npos && pos > first)
{
count = pos + 1 - first;
}
return s.substr(first, count);
}
};
void directory_listning_without_directories_demo()
{
set<string> output;
set<string> demo_set;
demo_set.insert("file1");
demo_set.insert("file2");
demo_set.insert("folder/file1");
demo_set.insert("folder/file2");
demo_set.insert("folder/folder/file1");
demo_set.insert("folder/folder/file2");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
demo_set.insert("bin/obj/Debug/vc100.idb");
demo_set.insert("bin/obj/Debug/vc100.pdb");
std::transform(demo_set.begin(),
demo_set.end(),
std::inserter(output, output.end()),
get_pertinent_part("bin/obj/Debug/"));
std::copy(output.begin(),
output.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
int main()
{
directory_listning_without_directories_demo();
cin.get();
return 0;
}
code sample based on this grate answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于没有transform_if,执行此操作的正确方法是首先将具有非零长度 get_pertinent_part 结果的路径复制到另一个容器中,然后在该新容器上运行转换。
或者,您可以编写类似transform_if 的内容,将转换函数的结果与谓词进行比较。这是我未经测试的尝试:
然后你可以使用它,例如
对于更酷的语法,请查看 boost 的 Range 适配器:
As there is no transform_if, a proper way to do this would be to to first copy_if the paths that have a non-zero-length get_pertinent_part result into another container, and then run the transform on that new container.
Alternatively, you could write something like transform_if that compares the result of your transform function with a predicate. Here's my untested shot at it:
Then you could use that like
For even cooler syntax, check out boost's Range adaptors:
您可以使用
std::accumulate
(不是来自
而是来自
)来累加 匹配到你的输出。调用方式:
请注意
std::ref
的使用(来自
)。您不希望输出集被移动(加上对 std::accumulate 的调用结果被忽略,因此不会看到任何更改)。或者,如果您不想依赖std::ref
,则可以使用指针。编辑:呵呵,重新审视这个想法,这可以说并不比使用 std::for_each 并将输出的引用传递给函子的构造函数更好。 YMMV。
You can use
std::accumulate
(not from<algorithm>
but from<numeric>
) to, well, accumulate the matches into your output.Call as:
Note the use of
std::ref
(from<functional>
). You don't want the output set to be moved around (plus the result of the call tostd::accumulate
is ignored so no changes will be visible). Alternatively, if you don't want a dependency onstd::ref
, you can use pointers.edit: heh, revisiting this idea, this is arguably no better than using
std::for_each
and passing a reference to the ouput to the constructor of the functor. YMMV.