Nombre de STL para el “mapa” función de la programación funcional
-
01-10-2019 - |
Pregunta
Me gustaría ser capaz de escribir algo como
char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);
La función transform
parece ser similar, pero no va a autogenerar el tamaño de la colección resultante.
Solución
Puede utilizar std::back_inserter
en <iterator>
, aunque proporciona el tamaño delante es más eficiente. Por ejemplo:
string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"
Otros consejos
Esta pregunta se hizo antes de que el C ++ 11 estándar entró en vigor hoy en día ... tenemos std::transform()
como el (feo) equivalente de un 'mapa' de programación funcional. He aquí cómo se usa:
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);
Para que esto funcione, necesitará las siguientes observaciones:
- Para realizar la asignación eficiente, la función debe
map
no hacer el trabajo. En su lugar, debe guardar sus argumentos en un objeto temporal (en su caso, eso sería una instancia declass map::result<char(*)(char), vector<char> >
) - Esta
map::result
temporal debe tener una conversióntemplate <typename T> operator T
. - Cuando se asigna el
map::result
a unstd::vector<char>
, esta conversión es la única viable. - En el
class map::result<char(*)(char), vector<char> >::operator vector<char>
operador de conversión que tiene el tipo de entrada y de retorno, y la función de mapeo. En este punto se puede transformar de manera efectiva las entradas.
<edit>
Código
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);
}
Uso de esta manera:
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>();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow