Modifying algorithms. Part 1.
Algorithms that change all elements of a sequence
Contents
- 1. Algorithm for_each. Perform an operation on each element of the sequence.
- 2. Algorithm transform. Perform action for each element of a sequence
- 3. Algorithm fill. Fill the range with the desired values
- 4. Algorithm fill_n. Fill in the range with the required values.
- 5. Algorithm generate. Perform operation on each element of a sequence
- 6. Algorithm generate_n. Perform an operation on each element of the sequence
- Related topics
Search other resources:
1. Algorithm for_each. Perform an operation on each element of the sequence.
The for_each algorithm allows you to perform a given operation on each element of a sequence. This operation is specified by a function. The general form of a common implementation of the algorithm is as follows
template <class InputIterator, class Function> Function for_each( InputIterator first, InputIterator last, Function func);
where
- first – input iterator pointing to the first element of the range to be operated on;
- last – input iterator pointing to the last element of the range on which the operation is to be performed;
- func – function that defines the operation.
Example 1.
In the example, each element of the vector is multiplied by 2. For multiplication, the Mult2() function is used.
#include <iostream> #include <vector> #include <queue> #include <list> #include <algorithm> #include <functional> using namespace std; void Mult2(int& value) { value = value * 2; } void main() { // Algorithm for_each. Perform an operation on each element of a sequence // 1. Create dynamic array vector<int> V = { 4, 8, 9, 2, 10, 15 }; // 2. Call the for_each algorithm // Here the Mult2() function is used for_each(V.begin(), V.end(), Mult2); // each element of the vector is multiplied by 2 // 3. Output the resulting array vector<int>::iterator p1; p1 = V.begin(); while (p1 != V.end()) { cout << *p1 << " "; p1++; } cout << endl; }
Example 2.
In our example, each line of list<string> is reversed using the for_each algorithm (Reverse() function).
#include <iostream> #include <list> #include <algorithm> #include <functional> using namespace std; // A function that reverses a string void Reverse(string& s) { string s2 = ""; for (int i = 0; i < s.length(); i++) { s2 = s[i] + s2; } s.assign(s2); } void main() { // Algorithm for_each. Perform operation on each element of a sequence // 1. Create a list of strings list<string> L = { "abc", "def", "ghi", "jkl" }; // 2. Call the for_each algorithm // The Mult2() function is used here for_each(L.begin(), L.end(), Reverse); // each element of the list is reversed // 3. Display the resulting list list<string>::iterator it; it = L.begin(); while (it != L.end()) { cout << *it << endl; it++; } cout << endl; }
Result
cba fed ihg lkj
⇑
2. Algorithm transform. Perform action for each element of a sequence
The transform algorithm allows you to specify an operation to be performed on each element of a sequence or on a pair of elements in two output ranges. The operation can be specified as a unary or binary function. The declaration of the most common implementations of the algorithm is
template <class InputIterator, class OutputIterator, class UnaryFunction> OutputIterator transform( InputIterator first1, InputIterator last1, OutputIterator result, UnaryFunction func ); template <class InputIterator1, class InputIterator2, class OutputIterator, class BinaryFunction> OutputIterator transform( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryFunction func );
where
- first1, last1 – input iterators specifying the first output range for processing;
- first2 – input iterator specifying the second range for processing;
- result – output iterator pointing to the position of the first element in the destination range;
- func – unary or binary function that specifies an operation to be performed on one element or on several elements.
Example.
#include <iostream> #include <list> #include <algorithm> using namespace std; // A predicate that performs the operation on a single element of a sequence, // multiply the value of the value parameter by 5 int Mult_5(int value) { return value * 5; } // A predicate that performs an operation on two distinct elements. // These elements can be from different sequences. int Mult_AB(int a, int b) { return a * b; // return the product of the elements } int main() { // The transform algorithm – execute a function for each element of this sequence // 1. Using the algorithm in combination with the predicate. // 1.1. Create a sequence of numbers and print it to the console. list<int> L1 = { 2, 8, 1, 4, 3, 5, 7, 0, -2, 6, 3 }; cout << "L1 => "; for (int i : L1) cout << i << " "; cout << endl; // 1.2. Create another sequence the same size as the original one list<int> L2(L1.size()); // 1.3. Call the transform algorithm for the L1 list based on the Mult_5 predicate, // new L2 sequence is created transform(L1.begin(), L1.end(), L2.begin(), Mult_5); // 1.4. Output the resulting sequence L2 cout << "L2 => "; for (int i : L2) cout << i << " "; cout << endl; // 2. Using algorithm based on the lambda expression. // 2.1. Create a sequence of L3 zero values of size L1.size() list<int> L3(L1.size()); // 2.2. Create a second sequence, each element of which // is multiplied by 2 - call the transform algorithm transform(L1.begin(), L1.end(), L3.begin(), [](int a) { return a * 2; }); // 2.3. Display the resulting sequence cout << "L3 => "; for (int i : L3) cout << i << " "; cout << endl; // 3. Using the transform algorithm to perform operation on two sequences. // It is necessary to multiply the elements of the sequence L1 by the elements of the sequence L2 // 3.1. Create a new sequence of size L1.size() list<int> L4(L1.size()); // 3.2. Fill the L4 sequence with values L1[i]*L2[i] transform(L1.begin(), L1.end(), L2.begin(), L4.begin(), Mult_AB); // 3.3. Print the sequence L4 cout << "L1[i]*L2[i] => "; for (int i : L4) cout << i << " "; cout << endl; // 4. Using the transform algorithm to perform operation on two sequences based on a lambda expression. // Get a new sequence in which the sequences L1 and L2 are added element by element. // 4.1. Create a new L5 null sequence of size L1.size(). list<int> L5(L1.size()); // 4.2. Fill sequence L5 with values L1[i]+L2[i] based on lambda expression. transform( L1.begin(), // the begin of L1 L1.end(), // the end of L1, L1.end()-L1.begin() => this is the length of the resulting sequence L2.begin(), // the beginning of the second sequence, attached to L1 L5.begin(), // the beginning of the resulting sequence [](int a, int b) { return a + b; } // lambda expression that returns the sum of a and b ); // 4.3. Display the resulting sequence cout << "L1[i]+L2[i] => "; for (int i : L5) cout << i << " "; cout << endl; }
Result
L1 => 2 8 1 4 3 5 7 0 -2 6 3 L2 => 10 40 5 20 15 25 35 0 -10 30 15 L3 => 4 16 2 8 6 10 14 0 -4 12 6 L1[i]*L2[i] => 20 320 5 80 45 125 245 0 20 180 45 L1[i]+L2[i] => 12 48 6 24 18 30 42 0 -12 36 18
⇑
3. Algorithm fill. Fill the range with the desired values
The fill algorithm is designed to assign a value to each element in a given range. The declaration of the algorithm is
template <class ForwardIterator, class Type> void fill( ForwardIterator first, ForwardIterator last, const Type& value);
here
- first, last – direct iterators used to set the range;
- value – value that fills the range.
Example.
#include <iostream> #include <queue> #include <vector> #include <list> #include <functional> #include <algorithm> using namespace std; int main() { // The fill algorithm - fill the range with the desired values // 1. Declaring a 5-element vector vector<int> V(5); // 2. Fill the vector with value 10 fill(V.begin(), V.end(), 10); // 3. Display the vector on the screen cout << "V => "; for (int i : V) cout << i << " "; cout << endl; // 4. Declare a list of 10 elements list<double> L(10); // 5. Fill list with value 5.0 fill(L.begin(), L.end(), 5.0); // 6. Display the list on the screen cout << "L => "; for (double d : L) cout << d << " "; cout << endl; }
Result
V => 10 10 10 10 10 L => 5 5 5 5 5 5 5 5 5 5
⇑
4. Algorithm fill_n. Fill in the range with the required values.
The fill_n algorithm assigns a new value to a specified number of elements in a range, starting at a particular element.
A common implementation of the algorithm is as follows
template <class OutputIterator, class Size, class Type> OutputIterator fill_n( OutputIterator first, Size count, const Type& value);
where
- first – an iterator pointing to the beginning of the range;
- count – number of elements to be assigned;
- value – the value that is assigned to the elements of the range.
Example.
#include <iostream> #include <queue> #include <vector> #include <list> #include <functional> #include <algorithm> using namespace std; int main() { // The fill algorithm - fill the range with the desired values // 1. Declare a vector of 5 elements vector<int> V(5); // 2. Fill the first 3 elements of the vector with the value 10 fill_n(V.begin(), 3, 10); // 3. Display the vector on the screen cout << "V => "; for (int i : V) cout << i << " "; cout << endl; // 4. Declare a list of 10 elements list<double> L(10); // 5. Fill the first 7 elements of the list with the value 1.0 fill_n(L.begin(), 7, 1.0); // 6. Display the list on the screen cout << "L => "; for (double d : L) cout << d << " "; cout << endl; }
Result
V => 10 10 10 0 0 L => 1 1 1 1 1 1 1 0 0 0
⇑
5. Algorithm generate. Perform operation on each element of a sequence
The generate algorithm assigns values to each element in the range generated by the function object. The general form of algorithm is as follows
template <class ForwardIterator, class Generator> void generate( ForwardIterator first, ForwardIterator last, Generator gen);
where
- first, last – iterators defining the range of processed values;
- gen – object of a function called with no arguments to generate values to be assigned to each element in the range.
Example 1.
The example uses a lambda expression to write the value “abcd” in each row of the list L.
#include <list> #include <algorithm> #include <functional> using namespace std; void main() { // Algorithm generate. Perform an operation on each element of the sequence // 1. Create a list of strings list<string> L = { "abc", "def", "ghi", "jkl" }; // 2. Call the algorithm generate // Write "abcd" to each element of the list using a lambda expression. generate(L.begin(), L.end(), []() { return "abcd"; }); // 3. Display the resulting string list<string>::iterator it; it = L.begin(); while (it != L.end()) { cout << *it << endl; it++; } cout << endl; }
Example 2.
The example generates an array of numbers 5.0 by calling the Get5() function.
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; // A function that returns the number 5 double Get5() { return 5.0; } void main() { // Algorithm generate. Perform operation on each element of the sequence // 1. Create array of 10 numbers vector<double> V(10); // 2. Call algorithm generate // Write a number to each element of array using the Get5() function generate(V.begin(), V.end(), Get5); // 4. Display the resulting array vector<double>::iterator it; it = V.begin(); while (it != V.end()) { cout << *it << " "; it++; } cout << endl; }
Result
5 5 5 5 5 5 5 5 5 5
⇑
6. Algorithm generate_n. Perform an operation on each element of the sequence
The generate_n algorithm assigns a value to a given number of sequence elements that were generated by the function object. The algorithm returns the position after the last value assigned
template <class OutputIterator, class Diff, class Generator> void generate_n( OutputIterator first, Diff count, Generator gen);
where
- first – iterator pointing to the beginning of the range;
- count – the number of elements to which a value is assigned;
- gen – function object without arguments, used to generate values.
Example 1.
#include <iostream> #include <list> #include <algorithm> #include <functional> using namespace std; void main() { // Algorithm generate_n. Perform an operation on each element of the sequence // 1. Create a list of strings list<string> L; // 2. Create 5 empty strings L.resize(5, ""); // 3. Call the generate_n algorithm // Write "abcd" to each element of the list using a lambda expression generate_n(L.begin(), L.size(), []() { return "abcd"; }); // 4. Display the resulting list list<string>::iterator it; it = L.begin(); while (it != L.end()) { cout << *it << endl; it++; } cout << endl; }
Example 2.
In the example, an array of random numbers is formed, the value of which lies in the range [1; 10].
#include <iostream> #include <vector> #include <algorithm> #include <functional> #include <time.h> using namespace std; // A function that returns a random number between 1 and 10 inclusive int Get_1_10() { int value = rand() % 10 + 1; return value; } void main() { // Algorithm generate_n. Perform an operation on each element of a sequence // 1. Create an array of 10 numbers vector<int> V(10); // 2. Initialize the kernel to get random values srand(time(NULL)); // 2. Call the generate_n algorithm // Write a number to each array element using the Get_1_10() function generate_n(V.begin(), V.size(), Get_1_10); // 4. Display the resulting array vector<int>::iterator it; it = V.begin(); while (it != V.end()) { cout << *it << " "; it++; } cout << endl; }
⇑
Related topics
- Modifying algorithms. Part 2. Algorithms for exchanging values of sequence elements. Algorithms swap, swap_ranges, iter_swap
- Modifying algorithms. Part 3. Algorithms that replace elements of a sequence. Algorithms replace, replace_if, replace_copy_if, replace_copy
- Modifying algorithms. Part 4. Algorithms that extract individual elements or groups of elements from a sequence: remove, remove_if, remove_copy, remove_copy_if, unique, unique_copy
- Modifying algorithms. Part 5. Algorithms processing the sequence as a whole without changing the values of the elements: copy, copy_backward, reverse, reverse_copy, rotate, rotate_copy, random_shuffle
⇑