I was reading following question:
How to sum up elements of a C++ vector?, and I wanted to use second method (sum_of_elems =std::accumulate(vector.begin(),vector.end(),0);//#include <numeric>).
However, I don't have std::vector<int>, but std::vector<struct packet>. The packet is defined as following:
struct packet {
/// ...
int length() const;
///
}
and I want sum of packet lengths.
This is what I tried:
std::vector<packet> packets;
...
std::accumulate(packets.begin(), packets.end(), 0, [](const packet& a, const packet& b){return a.length() + b.length();});
but it doesn't work. In C#, I'd write something like
packet[] p;
p.Select(x => p.length()).Sum();
Is it possible to do something like that in C++? I can write method for iterating through the vector and doing it on my own, but I prefer the functional approach where possible.
I would note that the C# implementation is slightly different, in essence.
In C++ you are trying to add int and packet whilst in C# you first provide a transformation step from packet to int and then add ints.
The equivalent C++, without adaptation:
std::vector<size_t> lengths; // a length cannot be negative!
std::transform(packets.begin(),
packets.end(),
backward_inserter(lengths),
[](packet const& p) { return p.length(); });
auto const sum = std::accumulate(lengths.begin(), lengths.end(), 0ul);
Of course, it is wasteful to store the intermediate lengths, however it does work out of the box.
But because we are cool, let us have look at Boost.Range, and more precisely:
boost::accumulate
boost::transformed
Which have a bit of coolness like Linq:
#include <boost/range/numeric.hpp> // accumulate
#include <boost/range/adaptor/transformed.hpp>
size_t total_size(std::vector<packet> const& packets) {
return boost::accumulate(
packets | boost::transformed([](packet const& p) { return p.length(); }),
0ul);
}
You are accumulating via a binary operation. Your accumulated value starts with 0 (an int), so the left hand side of your binary operation has to be convertible-from 0 -- otherwise, how does it start adding?
Try this:
std::accumulate(
packets.begin(),
packets.end(),
0,
[](int a, const packet& b){
return a + b.length();
}
);
you can also do this via a simple loop:
int acc = 0;
for( const packet& p : packets ) {
acc += packets.length();
}
The first parameter of the accumulate operation is the running total. In your case, this is an integer, not a packet, so your lambda should be
[](int a, const packet& b) {return a + b.length();}
The problem is your accumulate function. Its first parameter has to be of the type you're trying to accumulate (int in this case) and add a value on top of that.
Your lambda function should look like this: [](int currTotal, const packet& b){return currTotal + b.length();}
Apart from lamba, you can change it to
std::accumulate(packets.begin(), packets.end(), 0, packet());
Where you can define functor as:
int operator() (int result, const packet& obj)
{
return result+ obj.length();
}
Related
So I have a map with a key as a string, and I want to sort that map by the first value in the strings.
I want to sort the strings like this:
10 - 20
40 - 50
60 - 80
200 - 400
420+
I have a couple of more maps that I sort alphabetically. But this doesn't work for this case, because it would sort on the first letter, so it will become:
10 - 20
200 - 400
40 - 50
60 - 80
420+
Which I obviously do not want.
I normally sort like this:
dropdowncategory.KeySort([](const string& A, const string& B) {
return A.Compare(B, ESearchCase::IgnoreCase) < 0;
});
Simple.
But in this case from the A and B I want to get the first number, convert it to int and sort on that.
So what I did is I wrote a function (Not able to test it yet, but it should get the first number from the string, this is not the problem.):
int GetIntFromString(string s) {
int value = 0;
string L, R;
if (s.Contains("-")) {
s.Split("-", &L, &R);
}
else{
s.Split("+", &L, &R);
}
value = FCString::Atoi(*L);
return value;
}
From this function I will get the first number in the string. Then I want to sort on that outcome.
What I tried is the following:
dropdowncategory.KeySort([](const string& A,const string& B) {
return GetIntFromString(A) < GetIntFromString(B);
});
and:
string SA, SB;
dropdowncategory.KeySort([SA,SB](string& A, string& B) {
return GetIntFromString(SA) < GetIntFromString(SB);
});
But I keep getting and error on the GetIntFromString function in the return value of the KeySort:
Error (active) an enclosing-function local variable cannot be referenced in a lambda body unless it is in the capture list.
I am not sure why though.
I guess I cannot use that function inside the KeySort because it is a local function, but I don't know how to fix that.
As stated in std::stoi documentation:
Discards any whitespace characters (as identified by calling isspace()) until the first non-whitespace character is found, then takes as many characters as possible to form a valid base-n (where n=base) integer number representation and converts them to an integer value.
(emphasis is mine) it does what you need already, so your lambda can be just:
dropdowncategory.KeySort([](const string& A,const string& B) {
return std::stoi(A) < std::stoi(B);
});
note, converting string to integer is not very simple operation so you may want to reorganize your data so you do not have to do it for that strings so many times.
You can try to express your intent: treat the entries as pairs of ints, and use existing sorting logic for that:
std::vector<std::tuple<int, int>> pairs;
std::transform(begin(dropdowncategory), end(dropdowncategory),
std::back_inserter(pairs),
[](auto s){
std::stringstream ss(s);
int i; ss >> i;
char dummy; ss >> dummy;
int j; ss >> j;
return std::make_tuple(i, j);
});
std::sort(begin(pairs), end(pairs)); // 30, 50 will come before 200, 210
// convert pairs back to strings?
FString SA, SB;
dropdowncategory.KeySort([SA,SB](FString& A, FString& B) {
return GetIntFromString(SA) < GetIntFromString(SB);
});
Here you have 2 local string vars, empty (I suppose, no idea what's FString). You provide a lambda as a sorting function. Usually such function should have signature bool(const Key& left, const Key& right), and your lambda almost satisfied this requirement (pay attention to const). left and right here will be two keys to compare, and you need to define this comparison to define your sorting order. So correct version would be:
dropdowncategory.KeySort([](const FString& A, const FString& B) {
return GetIntFromString(A) < GetIntFromString(B);
});
This still doesn't explain your error, mainly because I have no idea what the error is.
By the way, GetIntFromString should be a free function, or at least a static member function, because its implementation depends only on input parameters.
P.S. listen to #Slava in the question comments, which can lead to
dropdowncategory.KeySort([](const FString& A, const FString& B) {
return std::atoi(*A) < std::atoi(*B);
});
Mainly as an exercise I am implementing a conversion from base B to base 10:
unsigned fromBaseB(std::vector<unsigned> x,unsigned b){
unsigned out = 0;
unsigned pow = 1;
for (size_t i=0;i<x.size();i++){
out += pow * x[i];
pow *= b;
}
return out;
}
int main() {
auto z = std::vector<unsigned>(9,0);
z[3] = 1;
std::cout << fromBaseB(z,3) << std::endl;
}
Now I would like to write this using algorithms. E.g. using accumulate I could write
unsigned fromBaseB2(std::vector<unsigned> x,unsigned b){
unsigned pow = 1;
return std::accumulate(x.begin(),
x.end(),0u,
[pow,b](unsigned sum,unsigned v) mutable {
unsigned out = pow*v;
pow *= b;
return out+sum;
});
}
However, imho thats not nicer code at all. Actually it would be more natural to write it as an inner product, because thats just what we have to calculate to make the basis transformation. But to use inner_product I need an iterator:
template <typename T> struct pow_iterator{
typedef T value_type;
pow_iterator(T base) : base(base),value(1) {}
T base,value;
pow_iterator& operator++(){ value *= base;return *this; }
T operator*() {return value; }
bool operator==(const pow_iterator& other) const { return value == other.value;}
};
unsigned fromBaseB3(std::vector<unsigned> x,unsigned b){
return std::inner_product(x.begin(),x.end(),pow_iterator<unsigned>(b),0u);
}
Using that iterator, now calling the algorithm is nice an clean, but I had to write a lot of boilerplate code for the iterator. Maybe it is just my misunderstanding of how algorithms and iterators are supposed to be used... Actually this is just an example of a general problem I am facing sometimes: I have a sequence of numbers that is calculated based on a simple pattern and I would like to have a iterator that when dereferenced returns the corresponding number from that sequence. When the sequence is stored in a container I simply use the iterators provided by the container, but I would like to do the same, also when there is no container where the values are stored. I could of course try to write my own generic iterator that does the job, but isnt there something existing in the standard library that can help here?
To me it feels a bit strange, that I can use a lambda to cheat accumulate into calculating an inner product, but to use inner_product directly I have to do something extra (either precalculate the powers and store them in a container, or write an iterator ie. a seperate class).
tl;dr: Is there a easy way to reduce the boilerplate for the pow_iterator above?
the more general (but maybe too broad) question: Is it "ok" to use an iterator for a sequence of values that is not stored in a container, but that is calculated only if the iterator is dereferenced? Is there a "C++ way" of implementing it?
As Richard Hodges wrote in the comments, you can look at boost::iterator. Alternatively, there is range-v3. If you go with boost, there are a few possible ways to go. The following shows how to do so with boost::iterator::counting_iterator and boost::iterator::transform_iterator (C++ 11):
#include <iostream>
#include <cmath>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
int main() {
const std::size_t base = 2;
auto make_it = [](std::size_t i) {
return boost::make_transform_iterator(
boost::make_counting_iterator(i),
[](std::size_t j){return std::pow(base, j);});};
for(auto b = make_it(0); b != make_it(10); ++b)
std::cout << *b << std::endl;
}
Here's the output:
$ ./a.out
1
2
4
8
16
32
64
128
256
512
I want to multiply and divide all the elements of std::vector by constant in the same way as it is performed in C++ for ordinary types: at least the result should be integer when input vector has integer type and floating-point type otherwise.
I have found the code for multiplication based on std::multiplies and modified it with the replacement std::divides. As the result, the code works but not in the order I want it:
#include <iostream>
#include <vector>
#include <algorithm>
// std::vector multiplication by constant
// http://codereview.stackexchange.com/questions/77546
template <class T, class Q>
std::vector <T> operator*(const Q c, const std::vector<T> &A) {
std::vector <T> R(A.size());
std::transform(A.begin(), A.end(), R.begin(),
std::bind1st(std::multiplies<T>(),c));
return R;
}
// My modification for division. There should be integer division
template <class T, class Q>
std::vector <T> operator/(const std::vector<T> &A, const Q c) {
std::vector <T> R(A.size());
std::transform(A.begin(), A.end(), R.begin(),
std::bind1st(std::divides<T>(),c));
return R;
}
int main() {
std::vector<size_t> vec;
vec.push_back(100);
int d = 50;
std::vector<size_t> vec2 = d*vec;
std::vector<size_t> vec3 = vec/d;
std::cout<<vec[0]<<" "<<vec2[0]<<" "<<vec3[0]<<std::endl;
// The result is:
// 100 5000 0
size_t check = vec[0]/50;
std::cout<<check<<std::endl;
// Here the result is 2
// But
std::vector<double> vec_d;
vec_d.push_back(100.0);
vec_d = vec_d/50;
std::cout<<vec_d[0]<<std::endl;
// And here the result is 0.5
return 0;
}
How can I write my operator correctly ? I thought that std::bind1st would call division by c for each element, but it does the opposite somehow.
EDIT: I understand that I can write a loop, but I want to do a lot of divisions for big numbers, so I wanted it to be faster...
Using std::transform with C++11, I'd suggest making a lambda (see this tutorial) instead of using bind:
std::transform(A.begin(), A.end(), R.begin(), [c](T val) {
return val / c;
});
In my opinion, lambdas are almost always more readable than binding, especially when (like in your case) you're not binding all of the function's parameters.
Although if you're worried about performance, a raw for loop might be slightly faster, as there's no overhead of the function call and creating the lambda object.
According to Dietmar Kühl:
std::transform() may do a bit of "magic" and actually perform better than a loop. For example, the implementation may choose to vectorize the loop when it notices that it is used on a contiguous sequence of integers. It is, however, rather unlikely to be slower than the loop.
auto c_inverse= 1/c;
std::transform(A.begin(), A.end(), R.begin(), [c_inverse](T val) {
return val * c_inverse;
});
Similar to the other post, but it should be mentioned that rather than division, you will most likely see performance gains by multiplying by the inverse.
Why make it only for vectors? Here's a way to make more generic, to work with many types of containers:
template <class container, class Q>
container operator/(const container& A, const Q c) {
container R;
std::transform(std::cbegin(A), std::cend(A), std::back_inserter(R),
[c](const auto& val) {return val / c; });
return R;
}
Sure, it is expected to be a bit slower than with pre-allocation for a vector, since the back_inserter will allocate dynamically as it grows, but well, sometimes it might be appropriate to trade speed for genericity.
Given a pair of equal length arrays . .
void someFunc (const float **inputChannelData)
{
const float* L = inputChannelData[0];
const float* R = inputChannelData[1];
...
I can see that it is pretty easy to count the number of occurrences of a constant value using std::count . .
std::count(L, L+someIntegerOffset, 0.0f)
... but is there a standard algorithm (or idiom) that counts the element-wise (same index in each array) number of identical values in two arrays?
A Matlab equivalent would look like sum(L==R)
std::count has a predicate form std::count_if, and documentation suggest it gets the argument by lvalue.
So I believe I could hack together a lambda that captures the two arrays, from &arg gets the distance/index, then checks both values. I doubt I would use it that way though instead of old-fashioned for loop.
You can use zip for this, look here Sequence-zip function for c++11?
And then count_if with predicate, that tuple has only identical elements.
Also, you can simply create array of pairs and do the same.
Something like this for count with pairs.
void someFunc(const float** inputChannelData, size_t offset)
{
const float* R = inputChannelData[0];
const float* L = inputChannelData[1];
std::vector<std::pair<int, int>> pairs;
std::transform(L, L + offset, R, std::back_inserter(pairs),
[](float l, float r)
{
return std::make_pair(l, r);
});
size_t equal_pairs = std::count_if(pairs.begin(), pairs.end(),
[](const std::pair<float, float>& p)
{
return p.first == p.second;
});
}
I have an array of edges, which is defined as a C-style array of doubles, where every 4 doubles define an edge, like this:
double *p = ...;
printf("edge1: %lf %lf %lf %lf\n", p[0], p[1], p[2], p[3]);
printf("edge2: %lf %lf %lf %lf\n", p[4], p[5], p[6], p[7]);
So I want to use std::sort() to sort it by edge length. If it was a struct Edge { double x1, y1, x2, y2; }; Edge *p;, I would be good to go.
But in this case, the double array has a block size that is not expressed by the pointer type. qsort() allows you to explicitly specify the block size, but std::sort() infers the block-size by the pointer type.
For performance reasons (both memory-usage and CPU), let's say that it's undesirable to create new arrays, or transform the array somehow. For performance reasons again, let's say that we do want to use std::sort() instead of qsort().
Is it possible to call std::sort() without wasting a single CPU cycle on transforming the data?
Possible approach:
An obvious approach is to try to force-cast the pointer:
double *p = ...;
struct Edge { double arr[4]; };
Edge *p2 = reinterpret_cast<Edge*>(p);
std::sort(...);
But how do I make sure the data is aligned properly? Also, how do I make sure it will always be aligned properly on all platforms and architectures?
Or can I use a typedef double[4] Edge;?
How about having a reordering vector? You initialize vector with 1..N/L, pass std::sort a comparator that compares elements i1*L..i1*L+L to i2*L..i2*L+L, and when your vector is properly sorted, reorder the C array according to new order.
In response to comment: yes things get complicated, but it may just be good complication! Take a look here.
You can use a "stride iterator" for this. A "stride iterator" wraps another iterator and an integer step size. Here's a simple sketch:
template<typename Iter>
class stride_iterator
{
...
stride_iterator(Iter it, difference_type step = difference_type(1))
: it_(it), step_(step) {}
stride_iterator& operator++() {
std::advance(it_,step_);
return *this;
}
Iter base() const { return it_; }
difference_type step() const { return step_; }
...
private:
Iter it_;
difference_type step_;
};
Also, helper functions like these
template<typename Iter>
stride_iterator<Iter> make_stride_iter(
Iter it,
typename iterator_traits<Iter>::difference_type step)
{
return stride_iterator<Iter>(it,step);
}
template<typename Iter>
stride_iterator<Iter> make_stride_iter(
stride_iterator<Iter> it,
typename iterator_traits<Iter>::difference_type step)
{
return stride_iterator<Iter>(it.base(),it.step() * step);
}
should make it fairly easy to use stride iterators:
int array[N*L];
std::sort( make_stride_iter(array,L),
make_stride_iter(array,L)+N );
Implementing the iterator adapter all by yourself (with all operators) is probably not a good idea. As Matthieu pointed out, you can safe yourself a lot of typing if you make use of Boost's iterator adapter tools, for example.
Edit:
I just realized that this doesn't do what you wanted since std::sort will only exchange the first element of each block. I don't think there's an easy and portable solution for this. The problem I see is that swapping "elements" (your blocks) cannot be (easily) customized when using std::sort. You could possibly write your iterator to return a special reference type with a special swap function but I'm not sure whether the C++ standard guarantees that std::sort will use a swap function that is looked up via ADL. Your implementation may restrict it to std::swap.
I guess the best answer is still: "Just use qsort".
For the new question, we need to pass in sort() a kind of iterator that will not only let us compare the right things (i.e. will make sure to take 4 steps through our double[] each time instead of 1) but also swap the right things (i.e. swap 4 doubles instead of one).
We can accomplish both by simply reinterpreting our double array as if it were an array of 4 doubles. Doing this:
typedef double Edge[4];
doesn't work, since you can't assign an array, and swap will need to. But doing this:
typedef std::array<double, 4> Edge;
or, if not C++11:
struct Edge {
double vals[4];
};
satisfies both requirements. Thus:
void sort(double* begin, double* end) {
typedef std::array<double, 4> Edge;
Edge* edge_begin = reinterpret_cast<Edge*>(begin);
Edge* edge_end = reinterpret_cast<Edge*>(end);
std::sort(edge_begin, edge_end, compare_edges);
}
bool compare_edges(const Edge& lhs, const Edge& rhs) {
// to be implemented
}
If you're concerned about alignment, can always just assert that there's no extra padding:
static_assert(sizeof(Edge) == 4 * sizeof(double), "uh oh");
I don't remember exactly how to do this, but if you can fake anonymous functions, then you can make a comp(L) function that returns the version of comp for arrays of length L... that way L becomes a parameter, not a global, and you can use qsort. As others mentioned, except in the case where your array is already sorted, or backwards or something, qsort is going to be pretty much just as fast as any other algorithm. (there's a reason it's called quicksort after all...)
It's not part of any ANSI, ISO, or POSIX standard, but some systems provide the qsort_r() function, which allows you to pass an extra context parameter to the comparison function. You can then do something like this:
int comp(void *thunk, const void *a, const void *b)
{
int L = (int)thunk;
// compare a and b as you would normally with a qsort comparison function
}
qsort_r(array, N, sizeof(int) * L, (void *)L, comp);
Alternatively, if you don't have qsort_r, you can use the callback(3) package from the ffcall library to create closures at runtime. Example:
#include <callback.h>
void comp_base(void *data, va_alist alist)
{
va_start_int(alist); // return type will be int
int L = (int)data;
const void *a = va_arg_ptr(alist, const void*);
const void *b = va_arg_ptr(alist, const void*);
// Now that we know L, compare
int return_value = comp(a, b, L);
va_return_int(alist, return_value); // return return_value
}
...
// In a function somewhere
typedef int (*compare_func)(const void*, const void*);
// Create some closures with different L values
compare_func comp1 = (compare_func)alloc_callback(&comp_base, (void *)L1);
compare_func comp2 = (compare_func)alloc_callback(&comp_base, (void *)L2);
...
// Use comp1 & comp2, e.g. as parameters to qsort
...
free_callback(comp1);
free_callback(comp2);
Note that the callback library is threadsafe, since all parameters are passed on the stack or in registers. The library takes care of allocating memory, making sure that memory is executable, and flushing the instruction cache if necessary to allow dynamically generated code (that is, the closure) to be executed at runtime. It supposedly works on a large variety of systems, but it's also quite possible that it won't work on yours, either due to bugs or lack of implementation.
Also note that this adds a little bit of overhead to the function call. Each call to comp_base() above has to unpack its arguments from the list passed it (which is in a highly platform-dependent format) and stuff its return value back in. Most of the time, this overhead is miniscule, but for a comparison function where the actual work performed is very small and which will get called many, many times during a call to qsort(), the overhead is very significant.
std::array< std::array<int, L>, N > array;
// or std::vector< std::vector<int> > if N*L is not a constant
std::sort( array.begin(), array.end() );
I'm not sure if you can achieve the same result without a lot more work. std::sort() is made to sort sequences of elements defined by two random access iterators. Unfortunately, it determines the type of the element from the iterator. For example:
std::sort(&array[0], &array[N + L]);
will sort all of the elements of array. The problem is that it assumes that the subscripting, increment, decrement, and other indexing operators of the iterator step over elements of the sequence. I believe that the only way that you can sort slices of the array (I think that this is what you are after), is to write an iterator that indexes based on L. This is what sellibitze has done in the stride_iterator answer.
namespace
{
struct NewCompare
{
bool operator()( const int a, const int b ) const
{
return a < b;
}
};
}
std::sort(array+start,array+start+L,NewCompare);
Do test with std::stable_sort() on realistic data-sets - for some data mixes its substantially faster!
On many compilers (GCC iirc) there's a nasty bite: the std::sort() template asserts that the comparator is correct by testing it TWICE, once reversed, to ensure the result is reversed! This will absolutely completely kill performance for moderate datasets in normal builds. The solution is something like this:
#ifdef NDEBUG
#define WAS_NDEBUG
#undef NDEBUG
#endif
#define NDEBUG
#include <algorithm>
#ifdef WAS_NDEBUG
#undef WAS_NDEBUG
#else
#undef NDEBUG
#endif
Adapted from this excellent blog entry: http://www.tilander.org/aurora/2007/12/comparing-stdsort-and-qsort.html
Arkadiy has the right idea. You can sort in place if you create an array of pointers and sort that:
#define NN 7
#define LL 4
int array[NN*LL] = {
3, 5, 5, 5,
3, 6, 6, 6,
4, 4, 4, 4,
4, 3, 3, 3,
2, 2, 2, 2,
2, 0, 0, 0,
1, 1, 1, 1
};
struct IntPtrArrayComp {
int length;
IntPtrArrayComp(int len) : length(len) {}
bool operator()(int* const & a, int* const & b) {
for (int i = 0; i < length; ++i) {
if (a[i] < b[i]) return true;
else if (a[i] > b[i]) return false;
}
return false;
}
};
void sortArrayInPlace(int* array, int number, int length)
{
int** ptrs = new int*[number];
int** span = ptrs;
for (int* a = array; a < array+number*length; a+=length) {
*span++ = a;
}
std::sort(ptrs, ptrs+number, IntPtrArrayComp(length));
int* buf = new int[number];
for (int n = 0; n < number; ++n) {
int offset = (ptrs[n] - array)/length;
if (offset == n) continue;
// swap
int* a_n = array+n*length;
std::move(a_n, a_n+length, buf);
std::move(ptrs[n], ptrs[n]+length, a_n);
std::move(buf, buf+length, ptrs[n]);
// find what is pointing to a_n and point it
// to where the data was move to
int find = 0;
for (int i = n+1; i < number; ++i) {
if (ptrs[i] == a_n) {
find = i;
break;
}
}
ptrs[find] = ptrs[n];
}
delete[] buf;
delete[] ptrs;
}
int main()
{
for (int n = 0; n< NN; ++n) {
for (int l = 0; l < LL; ++l) {
std::cout << array[n*LL+l];
}
std::cout << std::endl;
}
std::cout << "----" << std::endl;
sortArrayInPlace(array, NN, LL);
for (int n = 0; n< NN; ++n) {
for (int l = 0; l < LL; ++l) {
std::cout << array[n*LL+l];
}
std::cout << std::endl;
}
return 0;
}
Output:
3555
3666
4444
4333
2222
2000
1111
----
1111
2000
2222
3555
3666
4333
4444
A lot of these answers seem like overkill. If you really have to do it C++ style, using jmucchiello's example:
template <int Length>
struct Block
{
int n_[Length];
bool operator <(Block const &rhs) const
{
for (int i(0); i < Length; ++i)
{
if (n_[i] < rhs.n_[i])
return true;
else if (n_[i] > rhs.n_[i])
return false;
}
return false;
}
};
and then sort with:
sort((Block<4> *)&array[0], (Block<4> *)&array[NN]);
It doesn't have to be any more complicated.