简体   繁体   中英

How can I filter a vector of strings in C++?

I have a big vector of 10000 strings:

std::vector<std::string> v;
for (int i = 0; i < 10000; i++) { v.push_back(generateRandomString(10)); }

I'd like to display the strings which contain "AB" as a substring. I tried:

std::vector<std::string> res;
res = std::copy_if(v, [](auto s) { return s.find("AB") != std::string::npos; });

cout << res;

But I get the following error:

error: no matching function for call to 'copy_if(std::vectorstd::__cxx11::basic_string<char >&, main(int, char**)::<lambda(auto:1)>)' std::vectorstd::string b = std::copy_if(a, [](auto s) { return s.find("AB") != std::string::npos; });

How can I filter a vector of strings and display only those which have "AB" as a substring?

(Will this be efficient if v contains 50MB of data?)

Something along these lines (untested):

std::copy_if(v.begin(), v.end(),
    std::ostream_iterator<std::string>(std::cout, "\n"),
    [](const std::string& s) { return s.find("AB") != std::string::npos; });

If you are looking for an efficient solution for just printing the strings you are interested in, you should avoid creating an intermediate data structure, ie you shouldn't use std::copy_if . Since C++20 you can use the range adaptor std::views::filter from the Ranges library together with a range-based for loop , as follows:

auto ab = [](const auto& s) { return s.find("AB") != std::string::npos; };
for (auto const& s : v | std::views::filter(ab))
    std::cout << s << std::endl;

This solution does not create a temporary vector for the filtered strings, because the view adaptor creates a range that doesn't contain elements. The resulting range is just a view over the vector v , but with a customized iteration behavior.

As of C++23 you can use std::string::contains to make the code even shorter and more readable, as follows:

auto ab = [](const auto& s) { return s.contains("AB"); };
for (auto const& s : v | std::views::filter(ab))
    std::cout << s << std::endl;

Code on Wandbox

However, if you want to also store the filtered result for further use, then you can combine the above solution with std::ranges::copy from the algorithms library , as follows:

std::vector<std::string> res;
std::ranges::copy(v | std::views::filter(ab), std::back_inserter(res));
for (auto const& s : res)
    std::cout << s << std::endl;

Code on Wandbox

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM