11
votes

somme de carré de chaque élément dans le vecteur en utilisant pour_achiser

Comme la fonction acceptée par for_each Prenez un seul paramètre (l'élément de la Vecteur), je dois définir un statique int somme = 0 code> quelque part pour que cela puisse être consulté Après avoir appelé le pour_achise. Je pense que c'est gênant. Toute meilleure façon de le faire (toujours utiliser pour_each)?

#map in ruby 
>> [1,2,3,4].map  {|i| i*i} 
=> [1, 4, 9, 16]

#inject in ruby 
[1, 4, 9, 16].inject(0)  {|aac ,i| aac +=i}  #=> 30


0 commentaires

6 Réponses :


22
votes

Utilisez std :: accumuler xxx

Vous pouvez imiter std :: accumuler comme dans La réponse de Belle Gman , mais je crois que l'utilisation de STD :: Accumulation rendra votre code plus lisible, car il a été conçu pour de telles fins. Vous pouvez trouver plus d'algorithmes standard ici .


4 commentaires

Je ne pense pas que les itérateurs de vecteur soient garantis dans l'espace de noms STD. Si cela est correct, ADL n'est pas garanti de travailler ici et le questionneur n'a pas spécifié de compilateur.


Tu as raison. Je viens de vérifier - standard ne garantit pas que Itérateur fait partie de l'espace de noms STD. Seuls les itérateurs inverse font partie de l'espace de noms std .


onebyone: wow, bonne prise. J'ai vérifié la norme et vous avez absolument raison. Alors par exemple Si le vecteur :: Itérateur a été typé de T *, ADL échouerait effectivement. -1ing pour attirer l'attention de l'OP ... (le post est autrement excellable BTW.)


Ok c'était rapide, pas besoin de -1 après tout! :)



7
votes

pour_achise retourne (une copie de) le fonctionnement qu'il utilisait. Donc, quelque chose comme ceci: xxx

comme illustré par d'autres réponses, cependant, std :: accumuler est le meilleur moyen d'aller.


2 commentaires

C'est un bon échantillon de STD :: Accumuler l'émulation. Utile à des fins d'enseignement.


Vote Down vote? Je ne peux pas améliorer si je ne sais pas ce qui ne va pas.



3
votes

En tant que solution générale à une telle question avec STL: au lieu de passer une fonction, vous pouvez transmettre un document - par exemple, une instance de n'importe quel opérateur d'implémentation de classe () . C'est beaucoup mieux que de s'appuyer sur les variables globales, car ce paramètre peut conserver et mettre à jour son propre État! Vous pouvez penser à cela comme une sorte de "compilée de dossier de canard": la programmation générique ne vous limite pas à transmettre une "fonction" à cet endroit, tout ce qui "se comporte comme une fonction" (c'est-à-dire disposer d'un opérateur approprié () ) fera aussi bien! -)


0 commentaires

4
votes

N'utilisez pas pour_ache () code> Pour cela, utilisez accumulez () code> dans le code> en-tête:

#include <numeric>
#include <iostream>
using namespace std;

struct accum_sum_of_squares {
    // x contains the sum-of-squares so far, y is the next value.
    int operator()(int x, int y) const {
        return x + y * y;
    }
};

int main(int argc, char **argv) {
    int a[] = { 4, 5, 6, 7 };

    int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
    cout << ssq << endl;
    return 0;
}


0 commentaires

49
votes

Non, n'utilisez pas STD :: Accumulez () Utilisez STD :: Inner_Product (). Aucun foncteur n'est requis.

#include <vector>
#include <numeric>

void main()
{
    std::vector <int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);

    int x = std::inner_product( v1.begin(), v1.end(), v1.begin(), 0 );
}


2 commentaires

Très élégant ... exactement ce que je cherchais!


Pourquoi ce n'est pas la meilleure réponse?



3
votes

std :: for_ach est de faire quelque chose avec chaque élément . Si vous voulez obtenir un résultat d'un calcul sur tous les éléments les éléments, il y a std :: accumuler . Si vous souhaitez que le comportement Carte de HASKELL'S , utilisez std :: transformer .

Vous pouvez abuser de ces trois à faire la même chose que l'une des autres, car, en fin de compte, ils ne sont que itérateurs sur un itérateur (à l'exception du formulaire Transformer qui prend deux itérateurs en tant qu'entrée. .) Le point est que pour_acheche n'est pas un remplacement pour la carte / pli - qui doit être effectué par transformation / accumulation - bien que C ++ n'a pas de natativement quelque chose qui exprime la carte / le concept de pliage ainsi que Haskell fait - mais à la fois GCC et VC ++ Support OpenMP qui a un bien meilleur analogue dans #pragma oomp parallèle pour .

injecter dans Ruby est une correspondance beaucoup plus proche de l'appelant pour_ache avec un fonctionnement à part entière, comme Gman a expliqué ci-dessus. Les fonctions Lambda avec capture variable en C ++ 0x rendent le comportement entre les deux langues encore plus similaires: xxx


0 commentaires