C++ equivalent to the python code: "for x in iterable:" [duplicate] - c++

This question already has answers here:
What is the correct way of using C++11's range-based for?
(4 answers)
Closed 7 years ago.
I want to do in c++ something like in python would be:
nums=[31, 46, 11, 6, 14, 26]
nlttf=[]
for n in nums:
if n<25:nlttf.append(n)

That would be the Range-based for loop:
SomethingIteratable cont;
for (const auto &v : cont) {
// Do something
}
As usual, const auto &v gives you immutable references, auto &v mutable references and auto v mutable deep copies.
Beware: You may not do anything in the loop that invalidates iterators of the container you iterate.

If you have C++11 then the code is the following:
for (int n: iterator) { /*Do stuff with n*/ }

If you have C++11 or greater, then you can do it this way.
#include <iostream>
#include <vector>
using namespace std;
int main() {
int num[] = {31, 46, 11, 6, 14, 26};
vector<int>nlttf;
for(int n:num){
if(n<25)nlttf.push_back(n);
}
return 0;
}
Read this Range-based for Statement (C++).
For std::vector see this and this link.

Here's another option, using C++11 and the boost libraries:
#include <iostream>
#include <boost/foreach.hpp>
#include <vector>
int main(){
std::vector<int> nums {31, 46, 11, 6, 14, 26};
std::vector<int> nltff;
BOOST_FOREACH(auto n, nums) if (n < 25) nltff.push_back(n);
BOOST_FOREACH(auto n, nltff) std::cout << n << " ";
std::cout << std::endl;
return 0;
}
Output:
11 6 14

Related

Correct way to invoke remove_if [duplicate]

This question already has answers here:
std::remove_if not working properly [duplicate]
(4 answers)
Closed 1 year ago.
In the following sample code remove_if is supposed to delete all even numbers but it is not working as I expect. I am obviously doing something wrong since the output continues to show some even numbers, towards the end.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool
myCond(int i) { return i % 2 == 0; }
int
main ()
{
vector<int> myVector = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22};
remove_if(myVector.begin(), myVector.end(), myCond);
for(int i : myVector) cout << i << " ";
cout << endl;
return 0;
}
output 11 13 15 17 19 16 17 18 19 20 22
std::remove_if only move the elements that need to be removed to the end of the container, you still need to use vector::erase to actually erase them.
If your compiler supports C++20, then I recommend using std::erase_if which is more intuitive and less error-prone:
vector<int> myVector = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22};
std::erase_if(myVector, myCond);
Demo.
remove_if returns an iterator - which will be the end of the rearranged items.
You can change you for loop to stop when it gets to the new end.
std::remove_if returns an iterator to the first element removed. In other words, everything before the iterator is evaluated to be false.
Have a look at the reference, especially the Return value paragraph.
For us, this means we have to iterate to returned iterator (the new end) if we want to print the odd values -- or we erase all elements from the returned iterator to end().
#include <iostream>
#include <vector>
#include <algorithm>
bool myCond(int i) { return i % 2 == 0; }
int main () {
std::vector<int> myVector = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22};
auto rm_it = std::remove_if(myVector.begin(), myVector.end(), myCond);
// Possibility 1: Print odd values
auto it = myVector.cbegin();
for (; it != rm_it; ++it) std::cout << *it << " ";
std::cout << std::endl;
// Possibility 2: Erase values from the vector
myVector.erase(rm_it, myVector.end());
for(int i : myVector) std::cout << i << " ";
std::cout << std::endl;
return 0;
}

how to add the numbers inside an array together C++ [duplicate]

This question already has answers here:
How to sum up elements of a C++ vector?
(13 answers)
Closed 2 years ago.
say I have an array that is an integer and stores five numbers, I want to add these numbers together and put them into a certain variable, how do I do this. if you have the answer to this then it would be greatly appreciated if you could respond. thanks.
Here is a simple code to sum integers:
Try it online!
#include <vector>
#include <iostream>
int main() {
std::vector<int> a = {1, 2, 3, 4, 5};
int res = 0;
for (auto x: a)
res += x;
std::cout << res << std::endl;
return 0;
}
Output:
15
Alternative way is to use std::accumulate:
Try it online!
#include <vector>
#include <iostream>
#include <numeric>
int main() {
std::vector<int> a = {1, 2, 3, 4, 5};
auto res = std::accumulate(a.begin(), a.end(), 0);
std::cout << res << std::endl;
return 0;
}

Range based for loop: Iterate over vector extended with one element

I want to achieve more less the equivalent to this Python code in C++ (but more memory efficient):
a = [1, 5, 3]
additional = 6
for elem in [additional] + a:
print(elem) # prints: 6 1 5 3
# alternative without creating the additional vector:
import itertools
for elem in itertools.chain([additional], a):
print(elem)
The only way that I know to do this in C++ is:
#include <iostream>
#include <vector>
int main() {
std::vector<int> a = {1, 5, 3};
int additional = 6;
for (int i = 0; i < a.size() + 1; ++i) {
int cur_elem;
if (i == 0) {
cur_elem = additional;
} else {
cur_elem = a[i-1];
}
std::cout << cur_elem << std::endl;
}
}
Is there a way to do this with a range based for loop? I found the Boost join operator but it seems to use only iterables, so I need to create an extra vector (like in the Python example).
Ideally, the iteration would be without creating the joined object in the memory and with algorithms of the standard library.
It can be done using the upcoming ranges feature.
Here's an example using Eric Niebler's range-v3 library:
#include <iostream>
#include <vector>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/single.hpp>
int main() {
std::vector<int> a = {1, 5, 3};
int additional = 6;
for (auto i : ranges::concat_view(ranges::single_view{additional}, a)) {
std::cout << i;
}
}
See it live!
by using views, all iterator operations are lazy, and no extra memory is used (e.g.: no extra vectors/arrays are created)
Or, without the for loop:
ranges::copy(ranges::concat_view(ranges::single_view{additional}, a), ranges::make_ostream_joiner(std::cout, ","));
See it live!
(Honestly, I like the for version better, though)
Standard-compliant solution
There's a small issue with the solution above: concat_view did not make it into C++20. If you want a strictly compliant solution, you may want to create your own version, or use join_view instead:
#include <iostream>
#include <vector>
#include <ranges>
int main() {
std::vector<int> a = {1, 5, 3};
int additional = 6;
std::vector v{{additional}, a};
for(int i : std::ranges::join_view{v}) {
std::cout << i;
}
}

C++ "select" algorithm

Among the functionalities found in std::algorithm I can't seem to find one of the most basic I can think of: selected a subset of a collection (for example, return all the odd numbers, all the employees that have status == 'employed', all items that cost less that 20 dollars).
So, given a list of ints like
vector<int> ints {1, 9, 3, 27, 5, 19, 3, 8, 2, 12};
vector<int> evens = ?
vector<int> greaterThan7 = ?
How to find those that are even and those that are greater than 7?
If you want something more functional, you can check out the boost range library. Specifically, filtered:
for (int i : ints | filtered([](int i){return i > 7;}))
{
...
}
This gives you a lazy view, without constructing a new container.
You can get the same from Eric Niebler's range-v3:
for (int i : view::filter(ints, [](int i){return i > 7;})
{
...
}
with the benefit that you can just assign that to a vector too (so you can choose if it's lazy or eager, which Boost.Ranges does not allow).
std::vector<int> greaterThan7 = view::filter(ints, [](int i){return i > 7;});
std::vector<int> sameThing = ints | view::filter([](int i){return i > 7;});
For example
vector<int> ints {1, 9, 3, 27, 5, 19, 3, 8, 2, 12};
vector<int> evens;
std::copy_if( ints.begin(), ints.end(), std::back_inserter( evens ),
[]( int x ) { return x % 2 == 0; } );
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> ints { 1, 9, 3, 27, 5, 19, 3, 8, 2, 12 };
std::vector<int> evens;
std::copy_if( ints.begin(), ints.end(), std::back_inserter( evens ),
[]( int x ) { return x % 2 == 0; } );
for ( int x : evens ) std::cout << x << ' ';
std::cout << std::endl;
}
Its output is
8 2 12
Depending on what your exact requirements are, consider std::stable_partition (or std::partition). It reorders elements in the range such that all which satisfy a predicate come first. You can think of it as splitting the range into a "subset" and a "not subset" part. Here is an example:
#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
using std::begin;
using std::end;
using std::cbegin;
using std::cend;
std::vector<int> ints { 1, 9, 3, 27, 5, 19, 3, 8, 2, 12 };
auto const greater_than_7 = [](int number) { return number > 7; };
auto const iter_first_not_greater_than_7 = std::stable_partition(begin(ints), end(ints), greater_than_7);
for (auto const_iter = cbegin(ints); const_iter != iter_first_not_greater_than_7; ++const_iter)
{
std::cout << *const_iter << "\n";
}
}
If, however, you are fine with copying each matching element to a new collection, for example because the source range must not be modified, then use std::copy_if.
Perhaps what you are really looking for is a view of an unmodifiable range. In this case, you are approaching the problem from the wrong direction. You don't need a particular algorithm; a more natural solution to the problem would be a filtering iterator, like for example Boost's Filter Iterator. You can use the one in Boost or study its implementation to learn how you could write filtering iterators yourself.

What is the C++ equivalent code of this Python slicing statement?

I am trying to translate the following Python statements to C++:
some_array = [11, 22, 33, 44]
first, rest = some_array[0], some_array[1:]
What I have so far is this:
int array[4] = {11, 22, 33, 44};
vector<int> some_array (array, 4);
int first = some_array.front();
vector<int> rest = some_array;
rest.erase(rest.begin());
How can this be shorter and/or efficiently rewritten?
Can this be written without using C++ templates and/or vectors?
Is there an online service (or software) for translating such non-trivial Python code snippets to human readable C++ code?
This:
vector<int> rest = some_array;
rest.erase(rest.begin());
can be shortened to:
vector<int> rest(some_array.begin() + 1, some_array.end());
If you can use C++11, you can shorten the whole code to:
vector<int> some_array { 11, 22, 33, 44 };
int first = some_array.front();
vector<int> rest (some_array.begin() + 1, some_array.end());
Although I doubt this would be much of an advantage...
The simplest way of doing this is
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> arr = {11, 22, 33, 44};
int first = arr[0];
vector<int> rest;
for (int i = 1; i < arr.size(); i++) {
rest.push_back(arr[i]);
}
return 0;
}
Or you can do this in this way also,
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> arr = {11, 22, 33, 44};
int first = arr[0];
vector<int> rest(arr.begin() + 1, arr.end());
return 0;
}