Skip to content

Instantly share code, notes, and snippets.

@sandrabosk
Last active November 9, 2023 22:17
Show Gist options
  • Save sandrabosk/21be342b2e39b76a22deb7e3938a227c to your computer and use it in GitHub Desktop.
Save sandrabosk/21be342b2e39b76a22deb7e3938a227c to your computer and use it in GitHub Desktop.

.sort()

  • mutates the original array - to prevent it, make a copy (const sorted = origArr.slice().sort() or const sorted1 = [...origArr]) of the array and then sort the copy
  • makes a specific order of elements
  • returns array
  • sorts by a string value (even if it's an array of numbers)

There's plenty of ways to sort arrays in JavaScript (and using .sort() is probably one of the slowest ones, but it is important to understand it and how it works).


Sorting numbers

  • Simple .sort()- sorts the values as strings in alphabetical and ascending order.

Yes, that is correct - although they are numbers, they will be sorted as strings. This means (and we will see it very soon) that although 11 is greater than 2, 11 will be sorted before 2 because "2" is bigger than "1". Because of this, the .sort() method will lead to incorrect result when sorting numbers.

Let's work on the following array:

const unsorted = [1, 4, 2, 11, 42];

Now apply the .sort() on the unsorted array of numbers:

unsorted.sort(); 
// [ 1, 11, 2, 4, 42 ] // <== sorted by string value!!!

Since we didn't make a safe copy of the array, let's check what happened with the original array:

console.log(`original: ${unsorted}`); // original: 1,11,2,4,42

Ups, it's sorted and we lost our original array. 😢

Let's see how we would approach with a best-practices in place:

const sorted1 = unsorted.slice().sort();

// const sorted1 = [...unsorted].sort();

console.log(`sorted: ${sorted1}`); // sorted: 1,11,2,4,42

console.log(`original: ${unsorted}`); // original: 1,4,2,11,42

You can fix this by providing a compare function.

Additional example
const x = "11";
const y = "2";

console.log(x < y); // true

The provided code is using JavaScript and it compares two strings, x and y, using the less than (<) operator. In this case, both x and y contain string representations of numbers, "11" and "2," respectively.

When you use the less than operator to compare strings in JavaScript, it performs a lexicographic (dictionary-style) comparison, character by character, from left to right. In this comparison, it starts by comparing the first characters of the strings. In this case, it compares "1" from x and "2" from y.

Since "1" comes before "2" in the lexicographic order (it has a lower character code in the character encoding used by JavaScript, typically UTF-16), the expression x < y evaluates to true.

So, the statement console.log(x < y) will output true to the console because "11" is indeed less than "2" when comparing them as strings, character by character. It's important to note that this behavior is specific to string comparisons, and if you were comparing numbers, you'd get a different result.

  • Using compare function with .sort() - yeah, that's it ✅

If we want to sort numbers in numerical order, we must include in the sort method one parameter: a compare function.

Let's get a new unsorted array:

const randomNumbers = [3, 1, 9, 8, 42, 1221];

The compareFunction parameter takes two arguments, which are typically referred to as a and b. The function should return a negative value if a should be sorted before b, a positive value if a should be sorted after b, or zero if a and b are equal.

function compareFunction(a,b){
    // < 0 --> a comes first
    // = 0 --> a nothing changes
    // > 0 --> b comes first
    
    return a - b;
}

🆙 Sorting numbers ascending

const ascRandom = randomNumbers.slice().sort((a, b) => a - b);
console.log(`sorted asc: ${ascRandom}`); // sorted asc: 1,3,8,9,42,1221

console.log(`original: ${randomNumbers}`); // original: 3,1,9,8,42,1221

We can see that numbers are sorted in ascending order and original array stayed untouched.

Sorting numbers descending

We will use the same array, randomNumbers:

const descRandom = randomNumbers.slice().sort((a, b) => b - a); 

console.log(`sorted desc: ${descRandom}`); // orted desc: 1221,42,9,8,3,1

console.log(`original: ${randomNumbers}`); // original: 3,1,9,8,42,1221

How does the compare function work?

The compare function should return a negative, zero or positive value, depending on the arguments.

Example:

When comparing 3 and 10, the .sort() method calls the compare function(3,10).

The function calculates 3-10 and returns -7 (a negative value).

The sort function will sort 3 as a value lower than 10.

Sorting strings

Let's see how it works when we sort the strings. We will be demoing on the array of words:

const words = ["Hello", "great", "First", "A", "a", "how"];

⬆️ Sorting strings ascending

Now, let's make a copy of the array and apply the simple sort. This method applied without compare function will sort strings in ascending order.

Note: The capitalized letters will come before lowercased ones.

const wordsAsc = words.slice().sort();

console.log(`words asc: ${wordsAsc}`); // words asc: A,First,Hello,a,great,how

console.log(`original words: ${words}`); // original words: Hello,great,First,A,a,how

To surpass this limitation, we should apply .toLowercase() on all words and then compare them:

const properWordsSortAsc = words.slice().sort((a,b) => {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if( a === b) {
        return 0;
    } else if(a > b) {
        return 1;
    } else {
        return -1;
    }
});

console.log(properWordsSortAsc);
// [ 'A', 'a', 'First', 'great', 'Hello', 'how' ]

🔽 Sorting strings descending

When in need to sort strings in descending order, we need to pass the following compare function (still working with the words array):

const wordsDesc = words.slice().sort((a, b) => {
    if( a === b){
        return 0;
    } else if(a > b) {
        return -1;
    } else {
        return 1;
    }
});

console.log(`words desc: ${wordsDesc}`); // words desc: how,great,a,Hello,First,A
console.log(`original words: ${words}`); // original words: Hello,great,First,A,a,how

Example: Sorting by length

const sortedByLength = words.slice().sort((a, b) => {
  if(a.length > b.length) {
      return 1;
  }
    
  if(a.length < b.length) {
      return -1;
  }
  if(a.length === b.length) {
      return 0;
  }
})

console.log('---> ', sortedByLength);
// --->  ['A', 'a', 'how',   'Hello', 'Hello', 'great', 'First' ]

Example with sorting by more than one condition

const arr = [
  { title: 'Carrot', votes: 3 },
  { title: 'Milk', votes: 2 },
  { title: 'Banana', votes: 2 },
  { title: 'Apple', votes: 1 }
];

const byVotesAlphabetically = arr.slice().sort((a, b) => {
  if (a.votes > b.votes) return -1;
  if (a.votes < b.votes) return 1;
  if (a.title > b.title) return 1;
  if (a.title < b.title) return -1;
});
console.log(byVotesAlphabetically);

// [
//   { title: 'Carrot', votes: 3 },
//   { title: 'Banana', votes: 2 },
//   { title: 'Milk', votes: 2 },
//   { title: 'Apple', votes: 1 }
// ]

Extra resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment