44

我希望能够写出类似的东西

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

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

4

5 回答 5

49

您可以使用std::back_inserterin <iterator>,尽管在前面提供尺寸更有效。例如:

string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"
于 2010-08-27T00:05:08.703 回答
24

这个问题是在 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);
于 2015-04-26T19:43:56.483 回答
4

要完成这项工作,您需要以下观察结果:

  1. 为了使分配有效,该map功能不应该这项工作。相反,它应该将其参数保存在一个临时对象中(在您的情况下,这将是 的一个实例class map::result<char(*)(char), vector<char> >
  2. 这个map::result临时应该有一个template <typename T> operator T转换。
  3. map::result分配给 astd::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>();
}
于 2010-08-27T09:04:18.767 回答
3

您可以使用类似的东西来模仿上面的地图语法

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;
}
于 2020-04-01T05:04:30.083 回答
0

std::transform功能可以完成工作,但在某些情况下无法执行。我建议使用while循环并事先保留大小。这个函数可以很容易地更改为与字符串或任何可映射的东西一起使用。

template<typename T, typename C>
std::vector<T> map(const std::vector<C> &array, auto iteratee) {
  int index = -1;
  int length = array.size();
  std::vector<T> v(length);
  while(++index < length) {
    v[index] = iteratee(array[index], index);
  }
  return v;
}

调用array要映射的 std::vector 所在的函数。

auto result = map<int, int>(array, [](int elem, int index) {
  return elem + 10;
});

在 100 000 000 上运行地图,std::transform耗时约 6.15 秒

while 循环版本耗时约 3.90 秒

于 2021-11-14T02:19:57.530 回答