Reputation: 13
I have file names and I need to check if these files end with any extension of the vector extensions; I would like to use some of the algorithms that are in the library instead of how I have done it, is there any way?
#include <iostream>
#include <algorithm>
#include <vector>
std::string tail(const std::string &st, const size_t len)
{
if (len >= st.size())
return st;
return st.substr(st.size() - len);
}
std::vector<std::string> filtered_files(const std::vector<std::string>& files, const std::vector<std::string>& extensions) {
std::vector<std::string> re;
for(const std::string f : files) {
for(const std::string ex : extensions) {
if(ex == tail(f,ex.size())) {
re.push_back(std::move(f));
break;
}
}
}
return re;
}
int main(int argc, char **argv) {
std::vector<std::string> v{"main.cpp","main.c","main.py"};
std::vector<std::string> re = filtered_files(v,{".c",".cpp"});
for(const std::string s :re) {
std::cout << s << '\n';
}
}
Upvotes: 1
Views: 672
Reputation: 598434
Have a look at the std::find_if()
standard algorithm in place of the inner loop. You can use the std::string::compare()
method to perform substring comparisons without having to actually allocate new std::string
objects, as your loops and tail()
function currently do. The only string allocations you need are for the strings pushed into re
(and even that allocation can be avoided if you return a std::vector<std::string*>
of pointers that point to the strings in te files
vector).
Try this:
#include <iostream>
#include <algorithm>
#include <vector>
std::vector<std::string> filtered_files(const std::vector<std::string>& files, const std::vector<std::string>& extensions)
{
std::vector<std::string> re;
for(const std::string &f : files)
{
if (std::find_if(extensions.begin(), extensions.end(),
[&](const std::string &ex){
return (f.size() >= ex.size()) && (f.compare(f.size()-ex.size(), ex.size(), ex) == 0);
}
) != extensions.end())
{
re.push_back(f);
}
}
return re;
}
Upvotes: 2
Reputation: 825
There are actually many ways of solving this, personally, this is the way I've achieved it before
#include <iostream>
#include <algorithm>
#include <string>
#include <functional>
#include <vector>
int main()
{
std::vector<std::string> v{"main.cpp","main.c","main.py"};
std::vector<std::string> ext{".cpp", ".c"};
std::vector<std::string> res;
for (auto& s : v) {
auto pos = s.find_last_of('.');
if (pos != s.npos) {
char* str = &s[pos];
if (std::any_of(ext.begin(), ext.end(),
[str](const string& a) { return str == a; })) {
res.push_back(s);
}
}
}
for (auto& r : res)
cout << r << endl;
return 0;
}
Upvotes: 1