1

I am wondering how I can sort a set that contains strings. For example, I have a set:

std::set<std::string> setA = {"B","A","C"}

Then I wanna use this to do the sorting:

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

But the C++ compiler cannot let it pass. The error message reports:

40: error: invalid operands to binary expression
('std::__1::__tree_const_iterator<std::__1::basic_string<char>, std::__1::__tree_node<std::__1::basic_string<char>, void *> *, long>'
and 'std::__1::__tree_const_iterator<std::__1::basic_string<char>, std::__1::__tree_node<std::__1::basic_string<char>, void *> *, long>')
difference_type __len = __last - __first;

Then I recheck sort function in C++, it seems that it can only deal with int, double, long ... but there is no way to use this function sort() to sort strings.

So how can I sort strings?

0

4 Answers 4

4

std::sort requires random access iterators while std::set provides only bidirectional iterators.

Generally speaking, any try to sort a std::set contradicts to the design of this container, because it stores its elements in the sorted order.

From the cppreference.com:

std::set is an associative container that contains a sorted set of unique objects of type Key.

Sign up to request clarification or add additional context in comments.

6 Comments

You can also say that it uses a red black tree most of the time. At least in gcc as it is apparent from the compilation from error. __tree_node
@Bugbugbuggerbuggered It is not significant how it stores its elements internally.
I do not want to get into details but the thing is any storage backend with a tree cannot provide random access iterator. It has to be sequential/linear(do not know which is more suitable word) storage.
@Bugbugbuggerbuggered I believe it can provide. But it would be inefficient.
Can does not mean will. It will be terribly inefficient not only inefficient.
|
0

You cannot resort a set, how it sorts is part of the type of the particular set. A given set has a fixed set order that cannot be changed.

You could create a new set with the same data relatively easily. Just create a new set that sorts based on the new criteria.

If you want to use the two sets in the same code, you'll have to abstract the access to the underlying set.

Copied shamelessly from Sorting Sets using std::sort. Change your container.

Comments

0

You just insert these three strings and they are already sorted if your using std::set

set<string> s;
s.insert("A");
...
OR
set<string> str = {"A", "B", "C", "D"}; //C++ 11
OR
string s[] = {"A", "B", "C", "D"};
set<string> str(s, s+ sizeof(s) / sizeof(s[0]));

And they are sorted.

If you want custom sorting (which is probably the case with you?)

Then use vector<string>() and sort()

bool cmp(string a, string b)
{
    // do something and return boolean
}
vector<string> v;
v.push_back("s");
...

sort(v.begin(),v.end(),cmp);

Btw you can't resort set as the sorting of it's elements is entirely upto the set's standard implementation as done in c++.

Comments

0

For ordering a set you can pass it a compare function during instantiation, like this:

#include <iostream>
#include <string.h>
#include <set>
using namespace std;
struct comp{
    bool compare()(const string& a, const string& b){
        return strcmp(a.c_str(),b.c_str()) < 0;
    }
};
int main(){
    set<string,comp> my_set = set<string,comp>();
    // or if you need duplicate entries then use multiset instead of set…
    multiset<string,comp> my_multiset = multiset<string,comp>();
    my_set.insert(“Bravo”);
    my_set.insert(“Alpha”);
    my_set.insert(“Lima”);
    my_set.insert(“Tango”);
    for (string s : my_set){
        cout<<s<<endl;
    }
    return 0;
}

I typed this out on my phone so forgive me if I messed something up but it should compile and run without errors. If I forgot an include statement try running it with:

#include <bit/stdc++.h> 

But I didn’t want to include that in the code I provided because its bad practice to use that include statement.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.