Generic algorithm: Tips (2)-accumulate

Source: Internet
Author: User
What if you want to accumulate all elements in a container?

The accumulate of STL allows us to write loops by ourselves:

# Include <iostream>
# Include <functional>
# Include <numeric>
# Include <vector>
# Include <string>

Int main ()
{
Std: vector <int> vect;
Vect. push_back (1 );
Vect. push_back (2 );
Vect. push_back (3 );
Vect. push_back (4 );

Std: cout <"Accumulate:" <
Std: accumulate (vect. begin (), vect. end (), 0, std: plus <int> ());
}

Output:

Accumulate: 10

Std: plus <int> () can be omitted, because it is the default action of the three parameters. Note that the accumulate algorithm is defined in numeric instead of algorithm.

Because both accumulate and plus are generic, if you want to accumulate a string instead of an int, the modification to the program is not great:

# Include <iostream>
# Include <functional>
# Include <numeric>
# Include <vector>
# Include <string>

Int main ()
{
STD: vector <STD: String> vect;
Vect. push_back ("1 ");
Vect. push_back ("2 ");
Vect. push_back ("3 ");
Vect. push_back ("4 ");

STD: cout <"accumulate:" <
STD: Accumulate (vect. Begin (), vect. End (), STD: string (""));
}

Output:
Accumulate: 1234

However, if boost. Lambda is used, there will be some nice-looking and easy-to-understand solutions to this problem:

# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <vector>
# Include <string>

# Include <boost/lambda. hpp>
# Include <boost/lambda/bind. hpp>
// # Include <boost/bind. hpp>

Using namespace boost: lambda;
// Using namespace boost;

Int main ()
{
Std: vector <std: string> vect;
Vect. push_back ("1 ");
Vect. push_back ("2 ");
Vect. push_back ("3 ");
Vect. push_back ("4 ");

Std: string result;

Std: for_each (vect. begin (), vect. end (), result + = _ 1 );

Std: cout <result;
}

Output:
1234

Here we need to borrow the variable result. There are several more lines in this program, but the purpose of calling accumulate is to put the result into a variable. In this way, boost is used. lambda looks pretty.

In the above program, another ugly thing is vector initialization. In order to put 1, 2, 3, and 4 in vect, we have to call push_back four times! However, using boost. lambda is much better.

Std: vector <int> vect (10 );
Int I = 0;
Std: for_each (vect. begin (), vect. end (), _ 1 = ++ var (I ));

There are two points worth noting:
1. You must specify the size in the vect statement. Otherwise, for_each will not do anything for an empty container.
2. You must use ++ var (I) instead of ++ I. The role of var here is to force lazy evaluation, that is, to evaluate the variable when it is used. If ++ I is used, you will get a vect with 10 values, instead of 1-10.

========================================================== ========================================================== =

Many problems will be complicated when it comes to map. What should we do if we want to accumulate all the keys or values in a map? At this time, you cannot directly use accumulate. You can use boost. bind to do this:

# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <map>
# Include <string>

# Include <boost/bind. hpp>

Using namespace boost;

Int main ()
{
Std: map <int, std: string> persons;
Persons [2, 123] = "Amy ";
Persons [234] = "Ralph ";
Persons [1, 345] = "Simon ";
Persons [1, 456] = "Maggie ";

Std: cout <std: accumulate (persons. begin (), persons. end (), 0,
Bind (std: plus <int> (), _ 1, bind (& std: map <int, std: string >:: value_type: first, _ 2 )))
<Std: endl;

Std: cout <std: accumulate (persons. begin (), persons. end (), std: string (),
Bind (std: plus <std: string> (), _ 1, bind (& std: map <int, std: string >:: value_type: second, _ 2 )))
<Std: endl;
}

Output:

1158
AmyRalphSimonMaggie

But in all fairness, it is not really beautiful. Continuous bind is not more dizzy than self-written loops. Boost. lambda also uses bind, but it can be much clearer:

# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <map>
# Include <string>

# Include <boost/lambda. hpp>
# Include <boost/lambda/bind. hpp>

Using namespace boost: lambda;

Int main ()
{
Std: map <int, std: string> persons;
Persons [2, 123] = "Amy ";
Persons [234] = "Ralph ";
Persons [1, 345] = "Simon ";
Persons [1, 456] = "Maggie ";

Int iresult = 0;
Std: string sresult;

Std: for_each (persons. begin (), persons. end (),
Iresult + = bind (& std: map <int, std: string >:: value_type: first, _ 1)
);

Std: for_each (persons. begin (), persons. end (),
Sresult + = bind (& std: map <int, std: string >:: value_type: second, _ 1)
);

Std: cout <iresult <std: endl;
Std: cout <sresult <std: endl;
}

The output is the same as the above:

1158
AmyRalphSimonMaggie

With its help, it will not be too difficult to add another layer of indirect layers: If your map does not directly store strings, but stores the Person object, their names must be obtained through the Name () method, and the code only needs to be slightly modified:

# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <map>
# Include <string>

# Include <boost/lambda. hpp>
# Include <boost/lambda/bind. hpp>

Using namespace boost: lambda;

Class Person
{
Public:
Person (){}
Person (const std: string & name): name _ (name ){}

Std: string & Name ()
{Return name _;}

Private:
Std: string name _;
};

Int main ()
{
Std: map <int, Person> persons;
Persons [1, 123] = Person ("Amy ");
Persons [234] = Person ("Ralph ");
Persons [1, 345] = Person ("Simon ");
Persons [1, 456] = Person ("Maggie ");

Std: string result;

Std: for_each (persons. begin (), persons. end (),
Result + = bind (& Person: Name, bind (& std: map <int, Person >:: value_type: second, _ 1 ))
);

Std: cout <result;
}

Output:

AmyRalphSimonMaggie

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.