问题
Is there a one liner (or a simple loop-free) solution to sort a vector by its even and odd indices? Example:
long entries[] = {0,1,2,10,11}; // indices 0 1 2 3 4
std::vector<long> vExample(entries, entries + sizeof(entries) / sizeof(long) );
vExample.sortEvenOdd(vExample.begin(),vExample.end()); // magic one liner I wish existed...
for (int i = 0; i < vExample.size(); i++)
{
std::cout << vExample[i] << " ";
}
Now I'd like to have the following output:
0 2 11 1 10 // corresponding to indices 0 2 4 1 3
回答1:
I tried to do a real one liner:
std::stable_partition(std::begin(input), std::end(input),
[&input](int const& a){return 0==((&a-&input[0])%2);});
And here is the full program:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> input {0,1,2,10,11};
std::stable_partition(std::begin(input), std::end(input),
[&input](int const& a){return 0==((&a-&input[0])%2);});
for (auto v : input)
std::cout << v << " ";
}
Ok I know, it works for the sole reason that vector uses a contiguous array of items and the whole thing is dirty... But for that's a one liner as asked by the OP and it doesn't require anything extra like boost...
回答2:
This is not one liner but pretty close:
long entries[] = {0,1,2,10,11}; // indices 0 1 2 3 4
std::vector<long> vExample;
for( bool flag : { true, false } ) {
auto cond = [&flag]( long ) { flag = !flag; return !flag; };
std::copy_if( std::begin( entries ), std::end( entries ), std::back_inserter( vExample ), cond );
}
回答3:
If you can use Boost, this is pretty concise:
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <iostream>
#include <vector>
int main() {
using namespace boost::adaptors;
std::vector<int> input {0,1,2,10,11};
std::vector<int> partitioned;
boost::push_back(partitioned, input | strided(2));
boost::push_back(partitioned, input | sliced(1, input.size()) | strided(2));
for (auto v : partitioned)
std::cout << v << " ";
}
You can of course wrap that in a function to get a one liner in the calling code. Live
回答4:
I don't like the messy business of fiddling with the addresses that the accepted answer of @fjardon proposes. @Slava's suggestion is much better and combined with the OP's code gives something that works quite well:
int main() {
std::vector<int> vals {0,2,3,-3,8,-5,7,8};
bool flag = true;
std::stable_partition(begin(vals), end(vals), [&flag] (auto el) mutable
{
// toggle flag, return previous value
flag = !flag; return !flag;
});
for (auto v : vals)
std::cout << v << " ";
}
Output: 0 3 8 7 2 -3 -5 8
回答5:
What you need is stable_partition. Define a predicate which checks whether the index is even using modulo 2, and you are good to go.
来源:https://stackoverflow.com/questions/33787939/sort-vector-by-even-and-odd-indices-c