Start learning free

LESSON 268 OF 675 · TUPLES, SORTING & BUILT-INS

Shortest Words First in TypeScript: Sorting by Two Rules

Practice Read the full explanation

You get an array of words, words. Return the words sorted from shortest to longest.

Words of the same length go in alphabetical order, from A to Z.

A word can appear more than once. Every copy stays in the result.

 

Example 1:

Input: words = ["banana", "fig", "apple", "kiwi"]
Output: ["fig", "kiwi", "apple", "banana"]
Explanation: "fig" has 3 letters and "kiwi" has 4.
"apple" has 5 and "banana" has 6.

Example 2:

Input: words = ["dog", "cat", "ant", "bee"]
Output: ["ant", "bee", "cat", "dog"]
Explanation: All four words have 3 letters.
So they go from A to Z.

Example 3:

Input: words = ["sun", "a", "moon", "sun"]
Output: ["a", "sun", "sun", "moon"]
Explanation: "sun" appears twice, so it stays twice.
Both copies come after "a" and before "moon".

 

Constraints:

  • words has 1 to 100 words.
  • Each word has 1 to 20 lowercase letters.
STEP 1 OF 3
    Ctrl + Enter to check

    TYPESCRIPT · TUPLES, SORTING & BUILT-INS

    Shortest Words First in TypeScript, explained

    Problem overview

    The method sortByLength gets an array of words and returns it sorted from shortest to longest. Words of the same length go in alphabetical order, A to Z. A word that appears twice stays twice. The array has 1 to 100 words of 1 to 20 lowercase letters.

    For ["banana", "fig", "apple", "kiwi"] the result is ["fig", "kiwi", "apple", "banana"]: lengths 3, 4, 5, 6. For ["dog", "cat", "ant", "bee"] all lengths are 3, so the result is ["ant", "bee", "cat", "dog"]. For ["sun", "a", "moon", "sun"] it is ["a", "sun", "sun", "moon"].

    Approach

    The array method sort accepts a compare function that takes two items, a and b, and returns a number. A negative number means a goes first, a positive number means b goes first, and 0 means they are tied. Here there are two rules, and the second only matters when the first ends in a tie:

    1. If the lengths differ, the shorter word goes first: return a.length - b.length. That is negative when a is shorter.
    2. Otherwise the lengths are equal, so order the words alphabetically with a.localeCompare(b).

    Why a compare function is needed

    Without one, sort() turns items into strings and compares them as text, which gives A to Z order and ignores length. And for numbers it gives [10, 9, 1].sort() equal to [1, 10, 9]. Always pass a compare function when the order is not plain text order.

    Step by step

    1. Call words.sort with an arrow function of a and b and a body in braces. The first line is an if: when a.length !== b.length, return a.length - b.length.
    2. Below the if, return a.localeCompare(b) for words of the same length.
    3. After the sort, return words.

    The solution in TypeScript

    class Solution {
        sortByLength(words: string[]): string[] {
            words.sort((a, b) => {
                if (a.length !== b.length) {
                    return a.length - b.length;
                }
                return a.localeCompare(b);
            });
            return words;
        }
    }
    

    sort changes the array it is called on and also returns it. That is why the method can return words after the call: it is now in order. If you need to keep the original order, sort a copy, for example [...words].sort(...).

    localeCompare returns a negative number, 0 or a positive number, which is exactly what a compare function needs. For lowercase letters it is plain A to Z order. It also compares mixed-case words the way a dictionary does: ["B", "a", "C"].sort() gives ["B", "C", "a"] (capitals first), while sorting with localeCompare gives ["a", "B", "C"]. This lesson has only lowercase words, so either is fine here.

    Duplicates need no special care. Sorting rearranges items and never drops them, and two equal words are simply tied (localeCompare returns 0).

    Tracing the third example

    In ["sun", "a", "moon", "sun"], comparing "a" with "sun": the lengths 1 and 3 differ, so the first rule returns a negative number and "a" goes first. Comparing "sun" with "moon": 3 and 4 differ, so "sun" goes first. Comparing the two "sun" words: the lengths match, and localeCompare returns 0, so they stay tied. The result is ["a", "sun", "sun", "moon"].

    Testing

    wordsResult
    ["banana", "fig", "apple", "kiwi"]["fig", "kiwi", "apple", "banana"]
    ["dog", "cat", "ant", "bee"]["ant", "bee", "cat", "dog"]
    ["sun", "a", "moon", "sun"]["a", "sun", "sun", "moon"]

    Common mistakes

    • Calling sort() with no function. The words come out in A to Z order, not by length.
    • Writing the rules the wrong way round. Checking the letters first would sort A to Z and only use the length for identical words.
    • Reversing the subtraction. b.length - a.length puts the longest word first.
    • Expecting a copy. The sorted array and the original are the same array.
    Keep going with TypeScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free