代码之家  ›  专栏  ›  技术社区  ›  Paul Nathan

“map”函数编程函数的STL名称

c++
  •  27
  • Paul Nathan  · 技术社区  · 14 年前

    我想写一些像

    char f(char);
    vector<char> bar;
    vector<char> foo = map(f, bar);
    

    这个 transform 函数看起来类似,但它不会自动生成结果集合的大小。

    3 回复  |  直到 5 年前
        1
  •  45
  •   Khaled Alshaya    14 年前

    你可以用 std::back_inserter <iterator>

    string str = "hello world!", result;
    transform(str.begin(), str.end(), back_inserter(result), ::toupper);
    // result == "HELLO WORLD!"
    
        2
  •  18
  •   einpoklum    6 年前

    这个问题是在C++ 11标准生效之前提出的。现在我们有 std::transform() 相当于函数式编程的“地图”。使用方法如下:

    auto f(char) -> char; // or if you like: char f(char)
    vector<char> bar;
    vector<char> foo;
    // ... initialize bar somehow ...
    std::transform(bar.begin(), bar.end(), std::back_inserter(foo), f);
    
        3
  •  3
  •   MSalters    10 年前

    1. 为了使任务更有效率 map 功能应该 做这项工作。相反,它应该将其参数保存在一个临时对象中(在您的示例中,该对象将是 class map::result<char(*)(char), vector<char> > )
    2. 这个 map::result 临时的应该有一个 template <typename T> operator T
    3. 映射::结果 分配给 std::vector<char> ,这种转换是唯一可行的。
    4. class map::result<char(*)(char), vector<char> >::operator vector<char> 您有输入和返回类型,以及映射函数。此时可以有效地转换输入。

    <edit>

    代码

    template<typename CONT, typename FUNC>
    class mapresult {
        CONT const& in;
        FUNC f;
    public:
        template<typename RESULT> RESULT to() const
        {
            RESULT out;
            for (auto const& e : in) { out.push_back(f(e)); }
            return out;
        }
        template<typename RESULT> operator RESULT() const
        {
            return this->to<RESULT>();
        }
        mapresult(CONT const& in, FUNC f) : in(in), f(std::move(f)) { }
    };
    
    template<typename CONT, typename FUNC>
    auto map(CONT const& in, FUNC f) -> mapresult<CONT, FUNC>
    {
        return mapresult<CONT, FUNC>(in, f);
    }
    

    像这样使用:

    using namespace std;
    char foo(char c) { return c | ('A' ^ 'a'); }
    std::string in = "Test";
    
    int main(int argc, char* argv[])
    {
        string out = map(in, &foo);
        cout << out << endl;
    
        char replace = 'e';
        cout << map(in, [replace](char c){return c == replace ? '?' : c; }).to<string>();
    }
    
        4
  •  1
  •   Don F    4 年前

    你可以模仿上面的map语法

    template<typename T, typename A>
    T map(A(*f)(A), T & container) {
        T output;
        std::transform(container.begin(), container.end(), std::back_inserter(output), f);
        return output;
    }