我希望能够像这样写一些东西:
char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);
transform
函数似乎很相似,但它不会自动生成结果集的大小。
我希望能够像这样写一些东西:
char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);
transform
函数似乎很相似,但它不会自动生成结果集的大小。
您可以在<iterator>
中使用std::back_inserter
,不过在前面提供大小更有效率。例如:
string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"
std::vector<t>::reserve
来消除效率惩罚。 - Billy ONeal在C++11标准生效之前,就有人问过这个问题... 现在我们有了std::transform()
作为函数式编程“map”操作的(丑陋的)等价物。以下是如何使用:
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);
map
函数不应该执行任务。相反,它应该将其参数保存在临时对象中(在您的情况下,这将是 class map::result<char(*)(char), vector<char> >
类的实例)。map::result
临时对象应该有一个 template <typename T> operator T
转换函数。map::result
被分配给一个 std::vector<char>
时,这个转换函数是唯一可行的。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>();
}
map
函数不知道目标容器。将映射输出存储到std::deque<char>
中,只是为了发现它实际上需要在std::vector<char>
中使用,这样做是低效的。 - MSalters.reserve(in.size())
时使用SFINAE。主要问题是将结果赋值给一个带有重载赋值运算符的类。 - MSalterstemplate<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;
}
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;
});
使用std::transform
在1亿个元素上运行map花费了约6.15秒
而while循环版本只花费了约3.90秒
std::map
作为集合。你可以在任何其他命名空间中拥有自己的map
。 - MSaltersmap
函数存在于 Perl、Python 和 Lisp 中,它是一个方便的高级构造,用于简单描述常见操作。 - Paul Nathan