nom de STL pour la fonction de programmation fonctionnelle « carte »
-
01-10-2019 - |
Question
Je voudrais pouvoir écrire quelque chose comme
char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);
La fonction transform
semble être similaire, mais il ne sera pas la taille autogenerate de la collection résultante.
La solution
Vous pouvez utiliser std::back_inserter
dans <iterator>
, bien que fournir la taille en face est plus efficace. Par exemple:
string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"
Autres conseils
Cette question a été posée la norme C ++ 11 est entré en vigueur ... Aujourd'hui, nous avons std::transform()
comme (laid) équivalent d'une programmation fonctionnelle « carte ». Voici comment l'utiliser:
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);
Pour faire ce travail, vous aurez besoin des observations suivantes:
- Pour l'affectation efficace, la fonction doit
map
pas faire le travail. Au lieu de cela, il doit enregistrer ses arguments dans un objet temporaire (dans votre cas, ce serait une instance declass map::result<char(*)(char), vector<char> >
) - Cette
map::result
temporaire devrait avoir une conversiontemplate <typename T> operator T
. - Lorsque le
map::result
est affecté à unstd::vector<char>
, cette conversion est la seule viable. - Dans l'opérateur de conversion
class map::result<char(*)(char), vector<char> >::operator vector<char>
vous avez le type d'entrée et le retour, et la fonction de cartographie. À ce stade, vous pouvez transformer efficacement les entrées.
<edit>
code
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);
}
Utiliser comme ceci:
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>();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow