Sorting a Std::Vector<Std::Pair<Std::String,Bool>> by the String

Sorting a std::vector std::pair std::string,bool by the string?

std::vector<std::pair<std::string, bool> > v;
std::sort(v.begin(), v.end());

std::pair overloads operator< to sort first by the first element then by the second element. Thus, if you just sort the vector using the default sort ordering (operator<), you'll get your desired ordering.

How to sort vector of pairs float, string regardless of string

std::pair has it's comparing operators overloaded (See the reference)

By default, operator < for std::pair compares first elements, if they are equal, then second elements.

You should provide your own predicate and use std::stable_sort to preserve the order of elements if first elements in pair are equal.

std::stable_sort(vec.begin(), vec.end(),
[](const auto& a, const auto& b){return a.first < b.first;});

Segfault from using std::sort on vector pair string, int

compare is somehow messed up and doesn't meet the requirements of Compare. Throw away the branching and simply do:

return p1.second > p2.second;

to sort in descending order. What you have is essentially a >=, which violates:

  • For all a, comp(a,a)==false
  • If comp(a,b)==true then comp(b,a)==false

and this results in undefined behavior.

How do I sort a vector of pairs based on the second element of the pair?

EDIT: using c++14, the best solution is very easy to write thanks to lambdas that can now have parameters of type auto. This is my current favorite solution

std::sort(v.begin(), v.end(), [](auto &left, auto &right) {
return left.second < right.second;
});

ORIGINAL ANSWER:

Just use a custom comparator (it's an optional 3rd argument to std::sort)

struct sort_pred {
bool operator()(const std::pair<int,int> &left, const std::pair<int,int> &right) {
return left.second < right.second;
}
};

std::sort(v.begin(), v.end(), sort_pred());

If you're using a C++11 compiler, you can write the same using lambdas:

std::sort(v.begin(), v.end(), [](const std::pair<int,int> &left, const std::pair<int,int> &right) {
return left.second < right.second;
});

EDIT: in response to your edits to your question, here's some thoughts ...
if you really wanna be creative and be able to reuse this concept a lot, just make a template:

template <class T1, class T2, class Pred = std::less<T2> >
struct sort_pair_second {
bool operator()(const std::pair<T1,T2>&left, const std::pair<T1,T2>&right) {
Pred p;
return p(left.second, right.second);
}
};

then you can do this too:

std::sort(v.begin(), v.end(), sort_pair_second<int, int>());

or even

std::sort(v.begin(), v.end(), sort_pair_second<int, int, std::greater<int> >());

Though to be honest, this is all a bit overkill, just write the 3 line function and be done with it :-P

How to sort a vector pair string , pair int , int ?

If you can't use C++11 features you can still do something like this:

typedef std::pair<std::string, std::pair<int, int>> AnkitSablok;

struct my_compare {
bool operator()(const AnkitSablok &lhs, const AnkitSablok &rhs) const {
return lhs.second < rhs.second;
}
};

int main()
{
std::vector<AnkitSablok> vec;

std::sort(vec.begin(), vec.end(), my_compare());
}

std::vector std::pair int, float and void error

You have two problems:

  1. sort does not return a copy of the sorted range. It modifies the range provided. If you want the original to be left alone, make a copy of it first and then sort it.

  2. std::sort's third argument is a comparator between two values, which has the meaning of "less than". That is, "does a come before b?" For keeping the line short, I replaced your pair<...> type with auto in the lambda, but it'll be deduced to "whatever type of thing" is being sorted.

Note, if you want decreasing, just change < to > in the lambda when it compares the two elements.

Possible fix:

    auto sorted = idx_correlations; // full copy
std::sort(sorted.begin(),
sorted.end(),
[](auto const & left, auto const & right) {
return left.first < right.first; });

After that, sorted will be a sorted vector and idx_correlations will be left unchanged. Of course, if you don't mind modifying your original collection, there's no need to make this copy (and you can take begin/end of idx_correlations.

Sorting vector of string pointers

std::string::compare returns an int, not a bool. According to cppreference.com the return value is

negative value if *this appears before the character sequence specified by the arguments, in lexicographical order

zero if both character sequences compare equivalent

positive value if *this appears after the character sequence specified by the arguments, in lexicographical order strong text

The returned value is cast to bool which evaluates to true for all non-zero values. That means that your function returns true for every non-identical pair of strings.

The C++ standard actually defines operator< for strings so you can change your function to

bool cmpStrPtrs(std::string *a, std::string *b) {
return *a < *b;
}

But that still leaves a big issue in your code. You absolutely do not need pointers for this. In fact, you are leaking memory right now because you neglect to delete them. The proper tool for this job is std::vector<std::string>. This has the added benefit that without the extra level of indirection, std::sort can implicitly call operator< without a helper function, leading to the following solution.

std::vector<std::string> vec;
vec.emplace_back("AAAAA");
vec.emplace_back("aaaaa");
vec.emplace_back("xxxxx");
vec.emplace_back("bfuen");
vec.emplace_back("xylophone");

std::sort(vec.begin(), vec.end());

sorting a string vector based on the string size

Make your own custom functor to compare the size of string(s) and use that to sort the strings.

struct compare {
inline bool operator()(const std::string& first,
const std::string& second) const
{
return first.size() < second.size();
}
};

std::vector<std::string> v;
compare c;
std::sort(v.begin(), v.end(), c);

In modern c++ we can use a lambda to do the same

std::vector<std::string> v;
std::sort(v.begin(), v.end(), []
(const std::string& first, const std::string& second){
return first.size() < second.size();
});


Related Topics



Leave a reply



Submit