Avez-vous écrit quelqu'un d'un algorithme compatible C ++ stl qui combine std :: transformer code> et
std :: accumule code> dans un algorithme de passage unique soutenant à la fois les unaires, binaires et peut-être Même (N-Ary!) Variante, disons
std :: transformé_accumulez code>? Je le souhaite parce que j'ai trouvé ce modèle très réutilisable dans l'exemple de l'algèbre linéaire par exemple dans les calculs de la norme (L1). La norme L1 calcule la somme des valeurs absolues des éléments. P>
5 Réponses :
uhm ... mon pari est que vous pouvez le faire en incorporant votre transformation en prédicat binaire, transmettant l'élément et accumulez après la transformation.
template <typename Transform> struct transform_accumulator_t { Transform t; transform_accumulator_t( Transform t ) : t(t) {} int operator()( int oldvalue, int newvalue ) const { return oldvalue + t(newvalue); } }; // syntactic sugar: template <typename T> transform_accumulator_t<T> transform_accumulator( T t ) { return transform_accumulator_t<T>(t); } int r = std::accumulate(v.begin(), v.end(), 0, transform_accumulator(times2));
Clever ... Peut-on peut-être simplifier cela en utilisant C ++ 11 Expressions Lambda?
@ Nordlöw: Bien sûr, si votre compilateur les prend en charge :)
Bien que cela puisse ne pas correspondre exactement à l'intention d'origine, Donc, pour votre L1, vous feriez quelque chose sur cet ordre général: P> seulement qui ne fonctionne pas tout à fait fonctionner - maintenant, il essaie de passer avec Ceci, votre normalisation L1 ressemblerait à ceci comme suit: P> std :: inner_product code> est fondamentalement votre version binaire. Vous le transmettez une valeur initiale, deux gammes et deux foncteurs, et il les applique comme:
std :: ABS code> où vous avez vraiment besoin d'une fonction binaire qui combine les deux entrées , mais je ne suis pas sûr de savoir comment les deux entrées sont vraiment censées être combinées. p>
std :: partiel_sum code> est assez proche de votre version unaire, sauf que cela accumule une Résultat, il (tente de) écrire chaque résultat intermédiaire, pas seulement le résultat final. Pour obtenir le résultat final, vous devez écrire (et passer une instance de) une sorte d'itérateur de rien qui ne contient que la valeur unique: p>
int main(){
double result=0.0;
double inputs[] = {1, -2, 3, -4, 5, -6};
std::partial_sum(
inputs, inputs+6,
make_res(result),
[](double acc, double v) {return acc + std::abs(v);});
std::cout << result << "\t";
return 0;
}
Merci encore plus pour les références pertinentes à d'autres algorithmes stl réutilisables.
Est std :: ajoute
@ Nordlöw: Oups - devrait être std :: plus
Si les lambdas sont disponibles, je préfère utiliser, disons, [] (t x, t y) {retour x + y; } code> sur
std :: plus
@ Nordlöw: Je vais le plus avec ce qui est le plus simple. Dans ce cas, cela semble être plus code>. L'exception serait si vous utilisez un lot i> de Lambdas de toute façon, auquel cas un mélange dans quelques foncteurs pré-conçus pourrait conduire à une confusion.
Si vous souhaitez utiliser un parallélisme, j'ai fait une version rapide à l'aide d'OpenMP:
double val = MapReduce_n(in, size, 0.0, [] (fftw_complex val) { return std::pow(val[0], 2.0) + std::pow(val[1], 2.0); }, std::plus<double>());
Agréable! Une chose si ... est std :: pow (X, 2.0) code> vraiment plus rapide que
x * x code> ?!
Selon celui-ci devrait être inllinée à l'autre Stackoverflow.com/questions/6321170/... . Cependant, je préfère écrire pow code> car il ressemble plus à la formule, et parce qu'il y a beaucoup d'autres
pow code> dans le logiciel, j'ai suivi ce code source. "Looks" sont cohérents.
Je suis surpris que personne a dit comment faire cela avec boost.Range: où v est un plage de cartes SINGE (c'est-à-dire n'importe quel conteneur STL). La surcharge des ABS doit être spécifiée, sinon cela serait aussi élégant que HASKELLL. P> P>
AS de C ++ 17 Il y a aussi https://fr.cppreference.com/w/cpp/algorithm/transform_reduce p> std :: transform_reduce code>, qui bénéficie également d'être parallélizable. P>
Si je ne me trompe pas, vous demandez à Mapreduce.