Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort Strings that have plus or minus

I am wondering if there is any way besides the very manual method of sorting the following (an example):

BBB+
BB
AA+
A-
BB-
A
B
AAA

We are trying to get the previous strings sorted as following :

AAA
AA+
A
A-    
BBB+
BB
BB-
B

Is there any automatic sort that compares plus and minus putting plus first?

like image 843
Afshin Ghazi Avatar asked Mar 05 '23 21:03

Afshin Ghazi


2 Answers

As I described in my comment, we can change the ratings into numbers so we can use basic sorting over complicated letter sorting.

	const ratings = [
		"BBB+",
		"BB",
		"AA+",
		"A-",
		"BB-",
		"A",
		"B",
		"AAA"
	];
	// Each letter should be enough apart.
	// Technically we can go for smaller numbers.
	// But that can break if not carefull once we start using Moodys or S&P instead of Fitch.
	// Since AA- is lower than AA, the - character has to be a negative number.
	const weights = {
		"A": 10000,
		"B": 1000,
		"C": 100,
		"D": 10,
		"+": 1,
		"-": -1
	};
	const rating_values = ratings
		.map( rating => ( {
			rating,
			"value": rating
				.split( '' )
				.map( character => weights[ character ] )
				.reduce( ( a, b ) => a + b )
		} ) );
	const sorted_ratings = rating_values
		.sort( ( a, b ) => b.value - a.value )
		.map( obj => obj.rating );
	console.log( sorted_ratings );
like image 65
Shilly Avatar answered Mar 19 '23 16:03

Shilly


You could use three step sorting by splitting the letters from plus/minus sign.

For getting a sortable value for '+' and '-', this approach uses a weight for these characters and takes zero for not given signs.

Then

  1. sort by the first character ascending,
  2. sort by the all characters descending,
  3. sort by weight ascending ('+' is smaller than '-')

var data = ['BBB+', 'BB', 'AA+', 'A-', 'BB-', 'A', 'B', 'AAA', 'AAA+', 'AAA-'];

data.sort((a, b) => {
    var weight = { '+': -1, '-': 1 },
        aa = a.split(/(?=[+\-])/),
        bb = b.split(/(?=[+\-])/);
        
    return aa[0][0].localeCompare(bb[0][0])
        || bb[0].localeCompare(aa[0])
        || (weight[aa[1]] || 0) - (weight[bb[1]] || 0);
});

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 26
Nina Scholz Avatar answered Mar 19 '23 16:03

Nina Scholz