I'm trying to sort an Eigen VectorXf x in ascending order.
This sorts it in descending order:
std::sort(x.data(),x.data()+x.size());
and this doesn't work:
bool myfunction (int i,int j) { return (i<j); }
std::sort(x.data(),x.data()+x.size(),myfunction);
any ideas?
Preface
Since the original question turned out to be a misunderstanding, and the code in it is already the proper answer, I decided to write up and post a bit about using std::sort in general.
std::sort sorts range in ascending order defined by weak ordering of the elements. By default it uses < operator defined on elements, but it can also take a function object or functor to provide the comparison. This functor needs to have properly overloaded function with signature of bool operator()(const T& lhs, const T& rhs) const. An example of this follows:
struct FooSorter {
bool operator (const Foo& lhs, const Foo& rhs) const {
return lhs.ham_index < rhs.ham_index;
}
};
/* ... */
std::sort(begin(vec), end(vec), FooSorter());
This would sort the full range represented by vec, according to criteria defined in FooSorter's operator().
Because writing custom functors for the simple things (sort in descending order, sort in ascending order) would quickly grow painful, STL provides many templated functors ready to use in functional header. The one relevant for sorting are:
std::equal_to implementing x == y
std::not_equal_to implementing x != y
std::greater implementing x > y
std::less implementing x < y
std::greater_equal implementing x >= y
std::less_equal implementing x <= y
All of these are templated and can be used for any type, that implements needed operators. Using these is easy:
std::sort(begin(vec), end(vec), std::greater<int>());
This would sort the range represented by vector in descending order.
But, since one of the biggest problems of STL algorithms was the pain of defining functors, C++11 brings a new trick: lambda functions. This lets you declare function object equivalent inline. Example follows:
std::sort(begin(vec), end(vec), [](int lhs, int rhs){return rhs > lhs});
This would also sort the range represented by vector in descending order, but we didn't have to explicitly declare a functor (or use already declared one). (This gets much better when implementing much more complex comparisons, or functors for different STL algorithms.)
If someone is looking for an answer, here how I did it. In this way, you can get eigenvalues and corresponding eigenvectors as well. Here covariance_matrix is the matrix in which eigenvalues and eigenvectors are to be solved.
std::vector<std::tuple<float, Eigen::VectorXf>> eigen_vectors_and_values;
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eigensolver(covariance_matrix);
if (eigensolver.info() != Eigen::Success) {
return;
}
Eigen::VectorXf eigen_values = eigensolver.eigenvalues();
Eigen::MatrixXf eigen_vectors = eigensolver.eigenvectors();
for(int i=0; i<eigen_values.size(); i++){
std::tuple<float, Eigen::VectorXf> vec_and_val(eigen_values[i], eigen_vectors.row(i));
eigen_vectors_and_values.push_back(vec_and_val);
}
std::sort(eigen_vectors_and_values.begin(), eigen_vectors_and_values.end(),
[&](const std::tuple<float, Eigen::VectorXf>& a, const std::tuple<float, Eigen::VectorXf>& b) -> bool{
return std::get<0>(a) < std::get<0>(b);
});
Note: Be careful when selecting which eigensolver is to be used. You may find here which one to be used: https://eigen.tuxfamily.org/dox/group__Eigenvalues__Module.html
Thanks for this complete answer for sorting both, eigenvalues and eigenvectors. Is it correct to return row() in
std::tuple<float, Eigen::VectorXf> vec_and_val(eigen_values[i], eigen_vectors.row(i));
From what is stated in the documentation of Eigen, it should be col()
Related
I want to use a map to count pairs of objects based on member input vectors. If there is a better data structure for this purpose, please tell me.
My program returns a list of int vectors. Each int vector is the output of a comparison between two int vectors ( a pair of int vectors). It is, however, possible, that the output of the comparison differs, though the two int vectors are the same (maybe in different order). I want to store how many different outputs (int vectors) each pair of int vectors has produced.
Assuming that I can access the int vector of my object with .inp()
Two pairs (a1,b1) and (a2,b2) should be considered equal, when (a1.inp() == a2.inp() && b2.inp() == b1.inp()) or (a1.inp() == b2.inp() and b1.inp() == a2.inp()).
This answer says:
The keys in a map a and b are equivalent by definition when neither a
< b nor b < a is true.
class SomeClass
{
vector <int> m_inputs;
public:
//constructor, setter...
vector<int> inp() {return m_inputs};
}
typedef pair < SomeClass, SomeClass > InputsPair;
typedef map < InputsPair, size_t, MyPairComparator > InputsPairCounter;
So the question is, how can I define equivalency of two pairs with a map comparator. I tried to concatenate the two vectors of a pair, but that leads to (010,1) == (01,01), which is not what I want.
struct MyPairComparator
{
bool operator() (const InputsPair & pair1, const InputsPair pair2) const
{
vector<int> itrc1 = pair1.first->inp();
vector<int> itrc2 = pair1.second->inp();
vector<int> itrc3 = pair2.first->inp();
vector<int> itrc4 = pair2.second->inp();
// ?
return itrc1 < itrc3;
}
};
I want to use a map to count pairs of input vectors. If there is a better data structure for this purpose, please tell me.
Using std::unordered_map can be considered instead due to 2 reasons:
if hash implemented properly it could be faster than std::map
you only need to implement hash and operator== instead of operator<, and operator== is trivial in this case
Details on how implement hash for std::vector can be found here. In your case possible solution could be to join both vectors into one, sort it and then use that method to calculate the hash. This is straightforward solution, but can produce to many hash collisions and lead to worse performance. To suggest better alternative would require knowledge of the data used.
As I understand, you want:
struct MyPairComparator
{
bool operator() (const InputsPair& lhs, const InputsPair pair2) const
{
return std::minmax(std::get<0>(lhs), std::get<1>(lhs))
< std::minmax(std::get<0>(rhs), std::get<1>(rhs));
}
};
we order the pair {a, b} so that a < b, then we use regular comparison.
I'm trying to sort a vector of unsigned int in lexicographical order.
The std::lexicographical_compare function only supports iterators so I'm not sure how to compare two numbers.
This is the code I'm trying to use:
std::sort(myVector->begin(),myVector->end(), [](const unsigned int& x, const unsigned int& y){
std::vector<unsigned int> tmp1(x);
std::vector<unsigned int> tmp2(y);
return lexicographical_compare(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end());
} );
C++11 introduces std::to_string
You can use from to_string as below:
std::sort(myVector->begin(),myVector->end(), [](const unsigned int& x, const unsigned int& y){
std::string tmp1 = std::to_string(x);
std::string tmp2 = std::to_string(y);
return lexicographical_compare(tmp1.begin(),tmp1.end(),tmp2.begin(),tmp2.end());
} );
I assume you have some good reasons, but allow me to ask: Why are you sorting two int's by using the std::lexicographical order? In which scenario is 0 not less than 1, for example?
I suggest for comparing the scalars you want to use std::less . Same as std lib itself does.
Your code (from the question) might contain a lambda that will use std::less and that will work perfectly. But let us go one step further and deliver some reusable code ready for pasting into your code. Here is one example:
/// sort a range in place
template< typename T>
inline void dbj_sort( T & range_ )
{
// the type of elements range contains
using ET = typename T::value_type;
// use of the std::less type
using LT = std::less<ET>;
// make its instance whose 'operator ()'
// we will use
LT less{};
std::sort(
range_.begin(),
range_.end(),
[&]( const ET & a, const ET & b) {
return less(a, b);
});
}
The above is using std::less<> internally. And it will sort anything that has begin() and end() and public type of the elements it contains. In other words implementation of the range concept.
Example usage:
std::vector<int> iv_ = { 13, 42, 2 };
dbj_sort(iv_);
std::array<int,3> ia_ = { 13, 42, 2 };
dbj_sort(ia_);
std:: generics in action ...
Why is std::less working here? Among other obvious things, because it compares two scalars. std::lexicographical_compare compares two ordinals.
std::lexicographical_compare might be used two compare two vectors, not two elements from one vector containing scalars.
HTH
I have structure:-
typedef struct {
int x;
int y;
}point;
i declared array :-
point A[100];
i took inputs for A from user.
so how can we sort the array A on the basis of x element.
I know how to do it by writing a function.
But how to do it by using sort() function defined in algorithm.h in C++
You can pass a compare function to std::sort.
point A[100];
std::sort(A, A+100,
[](const point& f, const point& s) -> bool{
return f.x < s.x;
});
You can pass a comparator function as the third argument of sort.
Include algorithm of course.
#include<algorithm>
Define the comparator function. It should compare two points and return true if the first one should be before the second one (if first one is smaller than the second one) in the sorted array. The sort function in <algorithm> will use this comparator function to compare your items and put them in the right order. You can learn more about sorting algorithms here. If you need more advanced materials you can lookup "Introduction to Algorithms".
bool compare(const point& p1, const point& p2) {
return p1.x < p2.x;
}
Use sort and pass your array and the function like this:
int main () {
point A[100];
std::sort(A, A+100, compare);
return 0;
}
Write comparator:
inline bool ComparePoints(const point & first, const point & second) {
return first.x < second.x;
}
After that you can call std::sort():
std::sort(A, A + 100, ComparePoints);
Using lambdas:
std::sort(std::begin(A),std::end(A),[](point const& l,point const& r){return l.x<r.x;});
I would like to compare a vector with an array assuming that elements are in different order.
I have got a struct like below:
struct A
{
int index;
A() : index(0) {}
};
The size of the vector and the array is the same:
std::vector<A> l_v = {A(1), A(2), A(3)};
A l_a[3] = {A(3), A(1), A(2)};
The function to compare elements is:
bool isTheSame()
{
return std::equal(l_v.begin(), l_v.end(), l_a,
[](const A& lhs, const A& rhs){
return lhs.index == rhs.index;
});
}
The problem is that my function will return false, because the elements are the same, but not in the same order.
A solution is to sort the elements in the vector and array before "std::equal", but is there any better solution?
Using sort would be the way to go. Sorting in general is a good idea. And as far as I know it would result in the best performance.
Note: I would recommend passing the vectors as arguments. Rather than using the member variables. After doing that this would be a typical function that would be very well suited to inline. Also you might also want to consider taking it out of the class and/or making it static.
I have four std::vector containers that all might (or might not) contain elements. I want to determine which of them has the most elements and use it subsequently.
I tried to create a std::map with their respective sizes as keys and references to those containers as values. Then I applied std::max on the size() of each vector to figure out the maximum and accessed it through the std::map.
Obviously, this gets me into trouble once there is the same number of elements in at least two vectors.
Can anyone think of a elegant solution ?
You're severely overthinking this. You've only got four vectors. You can determine the largest vector using 3 comparisons. Just do that:
std::vector<blah>& max = vector1;
if (max.size() < vector2.size()) max = vector2;
if (max.size() < vector3.size()) max = vector3;
if (max.size() < vector4.size()) max = vector4;
EDIT:
Now with pointers!
EDIT (280Z28):
Now with references! :)
EDIT:
The version with references won't work. Pavel Minaev explains it nicely in the comments:
That's correct, the code use
references. The first line, which
declares max, doesn't cause a copy.
However, all following lines do cause
a copy, because when you write max =
vectorN, if max is a reference, it
doesn't cause the reference to refer
to a different vector (a reference
cannot be changed to refer to a
different object once initialized).
Instead, it is the same as
max.operator=(vectorN), which simply
causes vector1 to be cleared and
replaced by elements contained in
vectorN, copying them.
The pointer version is likely your best bet: it's quick, low-cost, and simple.
std::vector<blah> * max = &vector1;
if (max->size() < vector2.size()) max = &vector2;
if (max->size() < vector3.size()) max = &vector3;
if (max->size() < vector4.size()) max = &vector4;
Here's one solution (aside from Pesto's far-too-straightforward approach) - I've avoided bind and C++0x lambdas for explanatory purposes, but you could use them to remove the need for a separate function. I'm also assuming that with two vectors with an equal number of elements, which one is picked is irrelevant.
template <typename T> bool size_less (const T* lhs, const T* rhs) {
return lhs->size() < rhs ->size();
}
void foo () {
vector<T>* vecs[] = {&vec1, &vec2, &vec3, &vec4};
vector<T>& vec = std::min_element(vecs, vecs + 4, size_less<vector<T> >);
}
Here is my very simple method. Only interest is that you just need basic c++ to understand it.
vector<T>* v[] = {&v1, &v2, &v3, &v4}, *max=&v1;
for(int i=1; i < 4; ++i)
if (v[i]->size() > max->size()) max = v[i];
This is a modified version of coppro's answer using a std::vector to reference any number of vectors for comparison.
template <typename T> bool size_less (const T* lhs, const T* rhs) {
return lhs->size() < rhs ->size();
}
void foo () {
// Define vector holding pointers to the original vectors
typedef vector< vector<T>* > VectorPointers;
// Fill the list
VectorPointers vecs;
vecs.push_back(&vec1);
vecs.push_back(&vec2);
vecs.push_back(&vec3);
vecs.push_back(&vec4);
vector<T>& vec = std::min_element(
vecs.begin(),
vecs.end(),
size_less<vector<T> >
);
}
I'm all for over-thinking stuff :)
For the general problem of finding the highest/lowest element in a group, I would use a priority_queue with a comparator:
(copying shamelessly from coppro, and modifying...)
template <typename T> bool size_less (const T* lhs, const T* rhs)
{
return lhs->size() < rhs ->size();
}
vector* highest()
{
priority_queue<vector<T>, size_less<T> > myQueue;
...
...
return myQueue.top();
}
You could use a std::multimap. That allows multiple entries with the same key.