Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Sort on an array of Strings

Tags:

c++

sorting

Given an array of strings containing the seven colors of the rainbow but placed in random order, I am somehow supposed to sort this array to output Red, Orange, Green,....,Violet in that order. The order of rainbow colors. How can I sort this array?

like image 671
Hussein Avatar asked Oct 01 '12 12:10

Hussein


People also ask

How do you sort an array of strings?

To sort an array of strings in Java, we can use Arrays. sort() function.

How do you custom sort a string?

Custom Sort String in C++ We have to permute the characters of T so that they match the order that S was sorted. More specifically, if x occurs before y in S, then x will occur before y in the returned string. So if the S = “cba” and T = “abcd”, then the output will be “cbad”.

How do you sort a custom array?

To define custom sort function, you need to compare first value with second value. If first value is greater than the second value, return -1. If first value is less than the second value, return 1 otherwise return 0. The above process will sort the data in descending order.

Does bubble sort work on strings?

Sort given strings using Bubble Sort and display the sorted array. In Bubble Sort, the two successive strings arr[i] and arr[i+1] are exchanged whenever arr[i]> arr[i+1]. The larger values sink to the bottom and hence called sinking sort.


2 Answers

You should write a custom comparator. Here's how I would go about it.

//somewhere in initalization code;
std::map<string, int> mapOrder;
mapOrder["red"] = 1;
mapOrder["orange"] = 2;
...
mapOrder["violet"] = 7;


bool isRainbowLess(const std::string& a, const std::string& b)
{
    return mapOrder[a] < mapOrder[b];
}


int main()
{
    std::vector<std::string> myVector;
    ....
    std::sort(myVector.begin(), myVector.end(), &isRainbowLess);
}
like image 186
Armen Tsirunyan Avatar answered Sep 19 '22 21:09

Armen Tsirunyan


OK, please do not down vote it right away. I know this is a bad example. I wrote it be cause OP specifically asked for a no-STL solution, and to present how (bad) would/could it look like.

Well, there you go. The code is not completed. But you should get the general idea. One thing I did skip is the sorting of integers itself. Since it should be trivial. As you can see, the mapping, is a little bit of PIA and looks quite bad. But since you forbid to use STL there is no std::map. Moreover, I implied static size of N for all the tables. It could be allocated dynamically, no problem, and no std::vector.

I used else ifs for map* functions to mimick std::map functionality. Probably switch ... case could be used, but it should work pretty much the same on a decent compiler.

The code I wrote below is pretty much the same in terms of functionality provided as Armen's does. I would recommend his solution. I skipped same parts. So you can see it's uglier and more typing. It looks almost like pure C. Maybe with one modification if you really yearn for speed at very large cases. That would be using a temporary data structure that would hold mapped values, to sort it, and then map it back. Precisely I would advise to avoid calling map::operator[](const &T) (or any accessor) on std::string under high performance constraints to avoid hash computations. But that's only it.

There is also some more to discuss. Like what if you wanted two colors to have the same value, or use non-integer weights. STL based solution is way more adaptable.

Cheers.

The code:

/* This will map color literals (color names) to integers, which will associate them with 
   a numerical value, than can be used for comparison */
enum Colors { Red, Orange, Green, /*...*/ Violet };

/* this should read colors as std::string instances from the input array and assing
   the the appropriate color codes into output array at corresponding indexes     */
void mapString2Color( const std::string* input, int* output, size_t N ){
  for(size_t i = 0; i < N; i++){
    if ( input[i] == std::string("red") ) output[i] = Colors::Red;
    else if ( input[i] == std::string("orange") ) { output[i] = Colors::Orange; }
    else if ( input[i] == std::string("green") )  { output[i] = Colors::Green;  }
    /*...*/
    else if ( input[i] == std::string("violet") ) { output[i] = Colors::Violet; }
    else {/*unspecified color code */}
  }
}
/* this is supposed to do the opposite to mapString (i.e. put appropriate 
   string at output[i] based on input[i])  */
void mapColor2String( const int* input, std::string* output, size_t N ){
  for(size_t i = 0; i < N; i++){
    if ( input[i] == Colors::Red ) output[i] = std::string("red");
    else if ( input[i] == Colors::Orange ) { output[i] = std::string("orange"); }
    else if ( input[i] == Colors::Green  ) { output[i] = std::string("green");  }
    /*...*/
    else if ( input[i] == Colors::Violet ) { output[i] = std::string("violet"); }
    else {/*unspecified color index*/}
  }
}

void sort(int* array, size_t N){
 /* any in-place sort of your liking for table of (unsigned) integers */
}

main(){
  std::string[N] input_array;
  std::string[N] output_array;
  int[N] temp_array;

  //map (translate) colors to their numerical values
  mapString2Color(input_array, temp_array, N);
  //sort it
  sort(temp_array, N);
  //map (translate) the values back to color names
  mapColor2String(temp_array, output_array, N);
}
like image 30
luk32 Avatar answered Sep 23 '22 21:09

luk32