Is there a more straight-forward way to do this?
for_each(v_Numbers.begin(), v_Numbers.end(), bind1st(operator<<, cout));
Without an explicit for loop, if possible.
EDIT:
How to do this for std::cin with a std::vector if possible? (How to read n elements only)?
You could achieve this using std::copy into a std::ostream_iterator:
std::vector<int> v_Numbers; // suppose this is the type
// put numbers in
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout));
It would be even nicer if you add some suffix:
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"));
This assumes that your container is a vector<int>, so you will have to replace that part with the appropriate type.
Edit regarding reading input:
Conversely, you can copy from a range of std::istream_iterator into a vector using std::back_inserter:
std::vector<int> v_Numbers;
std::copy(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(),
std::back_inserter(v_Numbers));
If you want to read n elements only, look at this question.
Another option — Boost.Lambda.
for_each(v.begin(), v.end(), cout << boost::lambda::_1);
Yep, but you must use std::copy algorithm:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> a;
// fill a...
std::copy(a.begin(), a.end(), std::ostream_iterator<int>(std::cout));
}
yup, using lambda expression (C++ 11) we can inline printing of each element of a STL container to cout.
#include <iostream> // cout
#include <vector> // vector
#include <algorithm> // for_each
#include <iterator> // istream_iterator
using namespace std;
int main()
{
std::vector<int> v(10,2);
std::for_each(v.begin(), v.end(), [](int i)->void {std::cout << i <<endl;});
return 0;
}
For reading "n" values from cin to vector,
int main()
{
std::vector<int> v;
int elementsToRead;
cin>>elementsToRead; // Number of elements to copy
// Reading from istream
std::istream_iterator<int> ii2(std::cin);
std::copy_n(ii2, elementsToRead, std::back_inserter(v));
// printing updated vector
std::for_each(v.begin(), v.end(), [](int i)->void {cout << i <<endl;});
return 0;
}
(or) by using Lambda expression
std::for_each(std::istream_iterator<int>(cin),std::istream_iterator<int>(),[&v](int i)->void { v.push_back(i);});
To know more about Lambda expression # What is a lambda expression in C++11?
Not always appropriate in corporate code, but for the sake of enumerating options - if you really find other for_each / std::copy etc. solutions too verbose, you could write:
std::ostream& operator(std::ostream& os, const std::vector<My_Type>& v)
{
// pick one of the other implementations for here...
std::copy(std::istream_iterator<My_Type>(os), std::istream_iterator<My_Type>(),
std::back_inserter(v_Numbers));
}
It's much nicer if you're well-mannered (;-p) enough to only overload your specific instantiation of vector (which requires My_Type be more than a typedef to say int, though it's not hard to create a templated class to create new types wrapping an arbitrary type). Otherwise, if someone else does the same elsewhere in your translation unit, the streaming could become ambiguous.
I know the copy with the iterator is the optimal solution, but just to answer with for_each.
You could do:
#include <vector>
#include <algorithm>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for_each(vec.begin(), vec.end(), [](auto &x){wcout << x << endl;});
return 0;
}
But, for me, it's REALLY much more readable the simple for ...
#include <vector>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for(auto &v: vec) {
wcout << v << endl;
}
return 0;
}
Related
I wanted a simple function that takes a collection of strings and appends them and returns one string which is each string item appended together. I thought std::accumulate was the way to go but interested to hear if this code could be improved.
Is there a simpler append type function that can be used here instead of the lambda?
Is this overly complicated and best achieved by some other code?
#include <string>
#include <vector>
#include <iostream>
#include <numeric>
std::string concatenate(std::vector<std::string> strings)
{
return std::accumulate(strings.begin(), strings.end(), std::string(""), [](std::string s1, std::string s2) { return s1 + s2; });
}
int main() {
std::vector<std::string> vec2{ "aaa","bbb","ccc","ddd","eee","fff" };
std::cout << concatenate(vec2) << std::endl;
}
Yes, you can omit the lambda entirely (or use std::plus<>{}).
Also the "" can be removed from std::string(""), or the whole third argument can be removed if you switch to std::reduce:
std::reduce(strings.begin(), strings.end());
Also concatenate should take the vector by a const reference, or even better a std::span<const std::string> (by value).
Also libfmt can be used for this:
fmt::format("{}", fmt::join(strings, ""));
It can be simplified with C++17 fold expression, there is no an intermediate or a temporary collection needed.
#include <string>
#include <iostream>
template<typename ...S>
std::string concatenate(S&&... strings) {
using namespace std::string_literals;
return (""s + ... + strings);
}
int main() {
std::cout << concatenate("aaa","bbb","ccc","ddd","eee","fff") << std::endl;
}
I noticed that I can seemingly get the same logic(copy elements matching some predicate into vector) both using ranges::copy_if and also using vector constructor taking 2 iterators(by providing it with filter_view .begin() and .end()).
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
#include <utility>
#include <fmt/ranges.h>
const std::vector<int> vals{1,2,3,47,8472};
const auto filter_pred = [](const int i){return i%2==0;};
void fna(){
std::vector<int> result;
std::ranges::copy_if(vals, std::back_inserter(result), filter_pred);
std::cout << fmt::format("{}", result) << std::endl;
}
void fn1(){
auto filtered = vals | std::views::filter(filter_pred);
std::vector<int> result {filtered.begin(), filtered.end()};
std::cout << fmt::format("{}", result) << std::endl;
}
std::vector<int> fna_val(){
std::vector<int> result;
std::ranges::copy_if(vals, std::back_inserter(result), filter_pred);
return result;
}
std::vector<int> fn1_val(){
auto filtered = vals | std::views::filter(filter_pred);
return {filtered.begin(), filtered.end()};
}
int main(){
fna();
fn1();
std::cout << fmt::format("{}", fna_val()) << std::endl;
std::cout << fmt::format("{}", fn1_val()) << std::endl;
}
Is there a reason to prefer one over other?
What I can think of:
it is unlikely that either is more efficient, since I doubt that any real optimizations can be done since because _if in copy_if means destination size is unknown.
compile speed: copy_if could be faster to compile since it does not require <ranges> header, but did not benchmark
const all the things: copy_if requires mutable destination container, range construction does not
verbosity: when return type of function is known we do not need to spell out the std::vector in body, {} works. Would be nice if vector understood ranges so we would not have to use .begin() .end(), but it does not.
Please explain with examples when to use std::logical_not and when std::not1!
According to documentation, the former is a "unary function object class" while the latter "constructs a unary function object". So at the end of the day both construct a unary function object, don't they?
Both are functors (a class with an operator()), but differ slightly on what they negate:
std::logical_not<T>::operator() returnsT::operator!(). Semantically, it sees T as a value and negates it.
std::not1<T>::operator() returns !(T::operator()(T::argument_type&)). Semantically, it sees T as a predicate and negates it.
std::not1<T> is a generalization of std::logical_not for more complex use case.
Please explain with examples when to use std::logical_not and when std::not1
Use std::logical_not whenever you can. Use std::not1 whenever your first option is out. The example on en.cppreference.com gives a case where std::not1 is necessary:
#include <algorithm>
#include <numeric>
#include <iterator>
#include <functional>
#include <iostream>
#include <vector>
struct LessThan7 : std::unary_function<int, bool>
{
bool operator()(int i) const { return i < 7; }
};
int main()
{
std::vector<int> v(10);
std::iota(begin(v), end(v), 0);
std::cout << std::count_if(begin(v), end(v), std::not1(LessThan7())) << "\n";
//same as above, but use a lambda function
std::function<int(int)> less_than_9 = [](int x){ return x < 9; };
std::cout << std::count_if(begin(v), end(v), std::not1(less_than_9)) << "\n";
}
I'm trying to read from file, and I know how to do that:
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
std::string filename = "data.txt";
std::ifstream from(filename);
std::vector<int> values((std::istream_iterator<int>(from)), std::istream_iterator<int>());
return 0;
}
My question is how to do the same thing in functional way:
int fromfile(std::string filename, std::vector<int> &values)
{
...
return 0;
}
The native way doesn't work:
int fromfile(std::string filename, std::vector<int> &values)
{
std::ifstream from(filename);
values((std::istream_iterator<int>(from)), std::istream_iterator<int>());
return 0;
}
Your functional way doesn't work because you're trying to use a constructor on an already constructed object - so it looks like you're trying to invoke operator() on your vector, which does not exist. However, vector does have an assign member function that does the same thing, without the need for extra parens:
int fromfile(std::string filename, std::vector<int> &values)
{
std::ifstream from(filename);
values.assign(std::istream_iterator<int>(from), std::istream_iterator<int>());
return 0;
}
Although the real functional way probably looks like this (C++11) - use the function to return the vector:
std::vector<int> fromfile(std::string filename)
{
std::ifstream from(filename)
return {std::istream_iterator<int>(from), std::istream_iterator<int>{}};
}
As is having an int return is somewhat useless if you just have return 0...
Notwithstanding the answer Barry has given to you, the other way to do this with algorithm is to call std::copy:
std::copy(std::istream_iterator<int>(from), std::istream_iterator<int>(),
std::back_inserter(values));
What is a good way to convert vector<vector<int>> vint to vector<vector<double>>vdouble?
I know from C++ convert vector<int> to vector<double> that this can be done for 1-D but I am not too sure how to do it for 2-d case.
Here's a pretty simple solution which uses emplace_back and the vector range constructor:
std::vector<std::vector<int>> intvec;
//intvec filled somehow
std::vector<std::vector<double>> doublevec;
doublevec.reserve(intvec.size());
for (auto&& v : intvec) doublevec.emplace_back(std::begin(v), std::end(v));
#include <iostream>
#include <vector>
#include <algorithm>
double castToDouble(int v) {
return static_cast<double>(v);
}
int main() {
std::vector<std::vector<int>> intv;
std::vector<std::vector<double>> doublev;
std::transform(intv.begin(), intv.end(), std::back_inserter(doublev), [](const std::vector<int> &iv) {
std::vector<double> dv;
std::transform(iv.begin(), iv.end(), std::back_inserter(dv), &castToDouble);
return dv;
});
return 0;
}
The naive solution is to use two loops, one nested inside the other, preferably range-based for loops.
You could also use e.g. std::transform with a lambda expression that in turn also calls std::transform on the nested vector, which does the actual conversion.
If you use std::transform remember to set the size of the destination vector, or use e.g. std::back_inserter.
A simple way is with std::transform and the range constructor of std::vector. If you're using back_inserter, you should reserve() some capacity to avoid repeated reallocations.
Live example: http://coliru.stacked-crooked.com/a/84ef0e3d6572792a
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<std::vector<int>> vvi = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
std::vector<std::vector<double>> vvd;
vvd.reserve(vvi.size());
std::transform(begin(vvi), end(vvi), std::back_inserter(vvd),
[](const std::vector<int>& vi) {
return std::vector<double>(begin(vi), end(vi));
});
// Output the destination container for verification:
for_each(begin(vvd), end(vvd), [](const std::vector<double>& vd){
std::copy(begin(vd), end(vd), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n";});
}