14

I have an array of school grades that looks like the following.

(Note 'N' stands for no grades and 'K' stands for kindergarten)

const toSort = ['1','3','4','5','6','7','9','10','11','12','K','2','N','8'];

Using the JavaScript sort() method, I would like to arrange the array so it will look like:

const sorted = ['K','1','2','3','4','5','6','7','8','9','10','11','12','N'];

Here is my attempt at it:

const toSort = ['1', '3', '4', '5', '6', '7', '9', '10', '11', '12', 'K', '2', 'N', '8'];

toSort.sort();
// Produces: ["1", "10", "11", "12", "2", "3", "4", "5", "6", "7", "8", "9", "K", "N"]

const test = toSort.sort((a, b) => {
  if (a === 'K') {
    return -1;
  }

  return Number(a) < Number(b) ? -1 : Number(a) > Number(b) ? 1 : 0;
});

console.log(test)

https://jsbin.com/pocajayala/1/edit?html,js,console,output

How I can resolve this?

7
  • 10
    Why K at the start and N at the end ? Commented Jul 27, 2018 at 14:51
  • 1
    What's the sorting logic that needs to be implemented? Why is K < 1 while N > 12? Commented Jul 27, 2018 at 14:52
  • 1
    These are school grades. 'N' stands for no grade, 'K' stands for kindergarten Commented Jul 27, 2018 at 14:52
  • 2
    Just like 'K', make a special case for 'N'. Then convert everything else to a Number. No need for any ternary operators. Commented Jul 27, 2018 at 14:54
  • 1
    Your issue is that Number("K") and Number("N") are both NaN. You only remove the case where the parameter a is "K", not where b is "K" or where either is "N". Commented Jul 27, 2018 at 14:55

4 Answers 4

22

You can use the string's native prototype localeCompare() function like so:

['1', '3', '4', '5', '6', '7', '9', '10', '11', '12', 'K', '2', 'N', '8']
    .sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))

//  ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "K", "N"]

It works well with numbers among other characters too.

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

2 Comments

Learned a new native function, thanks! that's a clean solution
What a smart solution. I really like this.
7

const toSort = ['1', '3', '4', '5', '6', '7', '9', '10', '11', '12', 'K', '2', 'N', '8'];

const test = toSort.sort((a, b) => {
	// console.log('a ' + a + ' b ' + b);
	if (a === "K" || b === "N") {
		return -1;
	}
	if (a === "N" || b === "K") {
		return 1;
	}
	return +a - +b;
});

console.log(test)

Comments

6

I would do it like this:

const toSort = ['1', '3', '4', '5', '6', '7', '9', '10', '11', '12', 'K', '2', 'N', '8'];

const transform = k => {
    if (k === 'K') return 0;
    else if (k === 'N') return 13;
    else return +k;
}

const test = toSort.sort((a, b) => transform(a) - transform(b));

console.log(test);

In case your letters don't have correlation with those specific numbers, and instead are always the biggest and the smallest, you can use Infinity and -Infinity on the transform function.

const transform = k => {
    if (k === 'K') return -Infinity;
    else if (k === 'N') return Infinity;
    else return +k;
}

1 Comment

return k == 'K' ? 0 : k == 'N' ? 13 : +k if you felt like minifying it.
0

I think this helps you

const toSort = ['1','3','4','5','6','7','9','10','11','12','K','2','N','8'];

toSort.sort(function(a, b) {
  if(a == 'K') {
    return -1; // always K is smaller
  }
  if(a == 'N')  {
    return 1 // always N is bigger
  }
  if(b == 'K') {
    return 1;
  }
  if(b == 'N')  {
    return -1
  }
  return Number(a) - Number(b);
});

console.log(toSort);

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.