0

How can i sort array/vector by repetition of elements? For example

Input

Leo
Mike
Eric
Leo
Leo

Output _ _ _ Or

Leo       Leo
Leo       Eric
Leo       Mike
Eric
Mike
9
  • And which language do you use? Commented Apr 11, 2011 at 14:39
  • Try std::sort(data.begin(), data.end()); Commented Apr 11, 2011 at 14:45
  • @user - Then write your own sort function. Commented Apr 11, 2011 at 14:48
  • @Ramhound: Why reinvent this wheel? Commented Apr 11, 2011 at 14:52
  • 2
    @James: I think he means for the most common element to appear first in the list, etc. Commented Apr 11, 2011 at 15:00

3 Answers 3

3

I recommend processing your data in 3 passes:

  1. Use std::sort to get all repeated elements adjacent to each other.

  2. Iterate over your sorted range recording the length and position of each equal_range.

  3. Now you can resort your sequence based on the data you've recovered in step 2. You may consider using stable_search in this phase if you could like a secondary search key to be alphabetical.

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

Comments

1

I would have liked to explain this in words and have you write the code, but I'm finding that I'm so familiar with C++ now, that it's a lot easier for me to just write code. Slight variation on what Steve said. Your original vector of strings is v.

std::map<std::string, int> m;
for(auto i=v.begin(); i!=v.end(); ++i)
    m[*i]++;

typedef std::pair<std::string, int> P;
auto comp_by_second = [](const P & lhs, const P & rhs) { return lhs.second < rhs.second; };

for(auto i=v.begin(); !m.empty(); )
{
    auto j = std::max_element(m.begin(), m.end(), comp_by_second);
    while(j->second-- > 0)
        *i++ = j->first;
    m.erase(j);
}

1 Comment

Pedantry Mode On: Your P typedef is wrong; the value type of a map<K, V> is pair<K const, V>. One technical fix would be to change it to typedef std::pair<std::string const, int> P;, but the preferred route is to use the map's value_type: typedef std::map<std::string, int>::value_type P;, or better yet its const_reference: typedef std::map<std::string, int>::const_reference P; auto comp_by_second = [](P lhs, P rhs) { ... };
0

There's no built-in way to do this. A relatively simple way is to build a map<string, size_t> containing the counts of each element (just iterate over your input vector, incrementing the count for each string you see). Then write all the keys in the map to a vector, and std::sort that vector with a comparator that compares the number from the map.

That involves more map lookups than strictly necessary, so you could instead write a vector of pairs from the map, then sort the pairs, and finally create your vector of strings from the sorted pairs.

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.