Nome STL per la “mappa” la funzione di programmazione funzionale
-
01-10-2019 - |
Domanda
Mi piacerebbe essere in grado di scrivere qualcosa come
char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);
La funzione transform
appare simile, ma non generare automaticamente la dimensione dell'insieme risultante.
Soluzione
È possibile utilizzare std::back_inserter
in <iterator>
, anche se fornisce la dimensione di fronte è più efficiente. Ad esempio:
string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"
Altri suggerimenti
Questa domanda è stato chiesto prima il C ++ standard di 11 è entrato in vigore ... oggi abbiamo std::transform()
come il (brutto) equivalente di un 'mappa' funzionali di programmazione. Ecco come usarlo:
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);
Per fare questo lavoro, avrete bisogno dei seguenti osservazioni:
- Per l'assegnazione efficiente, la funzione
map
dovrebbe non fare il lavoro. Invece, dovrebbe salvare i suoi argomenti in un oggetto temporaneo (nel tuo caso, che sarebbe un esempio diclass map::result<char(*)(char), vector<char> >
) - Questo
map::result
temporanea dovrebbe avere una conversionetemplate <typename T> operator T
. - Quando il
map::result
è assegnato a unstd::vector<char>
, questa conversione è l'unica praticabile. - Nella
class map::result<char(*)(char), vector<char> >::operator vector<char>
operatore di conversione si ha il tipo di ingresso e di ritorno, e la funzione di mappatura. A questo punto è possibile trasformare in modo efficace gli ingressi.
<edit>
Codice
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);
}
Usa come questo:
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>();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow