Start learning free

LESSON 267 OF 671 · SORTING & BUILT-INS

Shortest Words First in Go: Sorting with sort.Slice

Practice Read the full explanation

You get a slice 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

    GO · SORTING & BUILT-INS

    Shortest Words First in Go, explained

    Problem overview

    The function sortByLength receives a slice of strings, words, and returns it ordered from the shortest word to the longest. Words with the same length go in alphabetical order. A repeated word stays repeated, and sorting never removes anything.

    For banana, fig, apple, kiwi the result is fig kiwi apple banana. For sun, a, moon, sun it is a sun sun moon: both copies of sun stay, after a and before moon.

    Approach: two rules inside one comparison

    sort.Slice sorts a slice by your own rule. You give it the slice and a function of two indexes, i and j. The function returns true when the item at i must go before the item at j. Note that it receives indexes, not the words, so you read the words with words[i] and words[j].

    The order here has two rules, and the second only matters when the first can't decide:

    1. If the lengths differ, the shorter word goes first.
    2. If the lengths are equal, the word that comes first from A to Z goes first.

    Writing the first rule as an if that returns early, and the second as the final return, keeps them in the right priority.

    Step by step

    1. Call sort.Slice(words, func(i, j int) bool { ... }) and open the body. Inside, check whether len(words[i]) and len(words[j]) differ. If they do, return len(words[i]) < len(words[j]).
    2. Handle equal lengths with a final return words[i] < words[j]. The < operator on two strings compares them in dictionary order of their bytes, which for lowercase letters is alphabetical.
    3. Return words. sort.Slice reorders the slice itself and returns nothing, so the same variable now holds the sorted words.

    The solution in Go

    func sortByLength(words []string) []string {
        sort.Slice(words, func(i, j int) bool {
            if len(words[i]) != len(words[j]) {
                return len(words[i]) < len(words[j])
            }
            return words[i] < words[j]
        })
        return words
    }

    Two details are worth knowing. First, sort.Slice works in place: the caller's slice is changed too, because both share the same underlying array. To keep the original order, sort a copy made with slices.Clone. Second, sort.Slice is not stable, so equal items may swap places. That is why the second rule matters: with it, no two different words ever tie. Only identical words tie, and swapping those changes nothing visible.

    The function literal is written right where it is used and has no name. It can read words from the surrounding function, which is how it looks at the items.

    Testing

    Running the function on the statement's examples prints:

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

    Printing a slice with fmt.Println shows it in square brackets with spaces between the items, as above.

    Edge cases and common mistakes

    • Only the length rule. Without the second rule, words of equal length can come out in any order, and the lesson's tests expect A to Z.
    • Wrong direction. > on the lengths would put the longest word first.
    • Comparing the indexes. Writing i < j compares positions, not words, and sorts nothing.
    • Expecting a new slice. The sort changes words itself. If the original must survive, clone it first.
    • One word or repeated words. Both work with no special code.
    Keep going with Go500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free