【问题标题】:Filter std::vector of std::string's过滤 std::string 的 std::vector
【发布时间】:2012-11-21 11:12:33
【问题描述】:

如何生成一个输出向量,它根据输入向量是否以某个子字符串开头来过滤它。我正在使用 c++98 和 boost。

据我所知:

std::string stringToFilterBy("2");
std::vector<std::string> input = boost::assign::list_of("1")("2")("22")("33")("222");
std::vector<int> output;
boost::copy( input | boost::adaptors::filtered(boost::starts_with), std::back_inserter(output) );

【问题讨论】:

  • 你可以使用regex作为过滤器,它是boost & c++11的一部分
  • @Haocheng 但是,starts_with 谓词不是比正则表达式更有效吗?
  • 现在无法测试,但我认为您希望 boost::bind(boost::starts_with&lt;std::string,std::string&gt;(), _1, stringToFilterBy) 作为您的谓词。所以当过滤器适配器调用带有元素x的谓词时,它调用boost::starts_with(x, stringToFilterBy)
  • @Baz 是的...我刚才没听懂你的意思
  • @Steve Jessop boost::copy( 输入 | boost::bind(boost::starts_with<:string>(), _1, stringToFilterBy), std::back_inserter (输出) );这不编译。编译器抱怨starts_with 不接受零参数。

标签: c++ boost c++98


【解决方案1】:

您可以改用std::remove_copy_if

#include <algorithm>
#include <iterator>
#include <vector>

struct filter : public std::unary_function<std::string, bool> {
    filter(const std::string &by) : by_(by) {}
    bool operator()(const std::string &s) const {
        return s.find(by_) == 0;
    }

    std::string by_;
};

std::vector<std::string> in, out;
std::remove_copy_if(in.begin(), in.end(), std::back_inserter(out),
                    std::not1(filter("2")));

【讨论】:

  • 为什么这不起作用:std::remove_copy_if (input.begin(), input.end(), std::back_inserter(output), boost::bind(&boost::starts_with, _1, stringToFilterBy) );
  • @Baz 我很少用boost,所以我真的不能说。
  • @Baz 我终于安装了 boost 并测试了你的过滤器starts_withremove_copy_if 删除所有元素,其中filter 返回true。因此,对此的修复似乎正在否定这种情况。我对我的struct filter 犯了同样的错误并相应地修复了它。
【解决方案2】:

一种方法是:

#include <boost/algorithm/string/predicate.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/assign.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <iterator>
#include <vector>

int main() {
    std::string stringToFilterBy("2");
    std::vector<std::string> input =
        boost::assign::list_of("1")("2")("22")("33")("222");
    std::vector<int> output;
    boost::copy(
        input
      | boost::adaptors::filtered(
            boost::bind(
                boost::starts_with<std::string,std::string>, _1, stringToFilterBy))
      | boost::adaptors::transformed(boost::lexical_cast<int, std::string>),
        std::back_inserter(output));
}

或者不使用boost::bind(这样可以避免命名类型,也可以避免需要函数指针,但需要添加一些一次性结构体):

#include <boost/algorithm/string/predicate.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/assign.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <iterator>
#include <vector>

template<typename Range1T>
struct StartsWith_T {
    StartsWith_T(Range1T const& test) : test(&test) {}
    template<typename Range2T>
    bool operator()(Range2T const& input) const {
        return boost::starts_with(input, *test);
    }
    Range1T const* test;
};

template<typename Range1T>
StartsWith_T<Range1T> StartsWith(Range1T const& test) {
    return StartsWith_T<Range1T>(test);
}

template<typename T>
struct LexicalCaster {
    typedef T result_type;
    template<typename Input>
    T operator()(Input const& input) const {
        return boost::lexical_cast<T>(input);
    }
};

int main() {
    std::string stringToFilterBy("2");
    std::vector<std::string> input =
        boost::assign::list_of("1")("2")("22")("33")("222");
    std::vector<int> output;

    using namespace boost::adaptors;
    boost::copy(
        input
      | filtered(StartsWith(stringToFilterBy))
      | transformed(LexicalCaster<int>()),
        std::back_inserter(output));
}

【讨论】:

  • 第二个清单无法为我编译 - 很多模板错误 - 我正在尝试找出它是什么......
  • @Caribou:我的错……让我弄个固定版本
  • @Caribou:它们现在应该都可以工作了。 (我错过了result_type,适合我在 C++11 编译器上测试它)。
  • 我在那里玩得很开心 - 我从来没有使用过 boost 的这方面 :P - 调试这样的东西会让你学到更多:)
  • @Caribou:哦,如果是这样的话,我可以为您提供永无止境的损坏代码:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 2011-10-26
  • 2017-09-21
  • 2020-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多