Problem overview
The method sortByLength gets a list of words and returns them from shortest to longest. Words of the same length go in alphabetical order, and a word that appears twice stays twice. For ["banana", "fig", "apple", "kiwi"] the answer is ["fig", "kiwi", "apple", "banana"].
Approach
Plain sorted(words) orders alphabetically, giving ['apple', 'banana', 'fig', 'kiwi']. Sorting with key=len orders by length, but words of the same length keep their old relative order, not alphabetical order.
The fix is a key that returns a tuple. Python compares tuples position by position: first the lengths, and only when those are equal, the words themselves. So (3, "ant") < (3, "bee") is True, and (3, "fig") < (4, "kiwi") is True as well. One key gives both rules.
For the first example, the keys the sort sees are these:
| word | key |
|---|---|
| banana | (6, 'banana') |
| fig | (3, 'fig') |
| apple | (5, 'apple') |
| kiwi | (4, 'kiwi') |
Sorting these keys gives the order fig, kiwi, apple, banana. Here all the lengths differ, so the second part of each key is never needed. For ["dog", "cat", "ant", "bee"] all the lengths are 3, and the words decide the order. With only key=len, that list stays as ['dog', 'cat', 'ant', 'bee'], because the sort keeps the original order of equal keys.
Step by step
- Build
orderedwithsorted(words, key=...), where the key is a function from a word to(len(word), word). Alambdawrites that function inline. - Return
ordered. Sorting moves words around and never drops one, so duplicates stay.
The solution in Python
class Solution:
def sortByLength(self, words: List[str]) -> List[str]:
ordered = sorted(words, key=lambda word: (len(word), word))
return ordered
sorted returns a new list and leaves words alone. The list method words.sort() sorts in place and returns None, so ordered = words.sort() would make ordered equal to None. The key runs once per word to decide the order; the words in the result are the original ones.
Testing
["banana", "fig", "apple", "kiwi"] -> ['fig', 'kiwi', 'apple', 'banana']
["dog", "cat", "ant", "bee"] -> ['ant', 'bee', 'cat', 'dog']
["sun", "a", "moon", "sun"] -> ['a', 'sun', 'sun', 'moon']
More about sort keys
The key only decides the order; it never changes the items. A key can be any function of one item that returns something Python can compare: a number, a string or a tuple. Tuples are compared one position at a time, and a later position is looked at only when all earlier ones are equal. So you can chain as many rules as you need, most important first.
Strings compare by character code, so uppercase letters come before lowercase ones: sorted(["b", "B", "a"]) gives ['B', 'a', 'b']. The words in this lesson are all lowercase, so this doesn't matter here.
Edge cases
A list with one word comes back as a list with that word. Repeated words are fine: for ["sun", "a", "moon", "sun"] the keys of the two "sun" entries are equal, so they end up next to each other, giving ['a', 'sun', 'sun', 'moon']. Sorting never removes anything, so the result is always as long as the input.
Reversing the order
Adding reverse=True flips the whole key order. For the first example it gives ['banana', 'apple', 'kiwi', 'fig'], longest first. That would also turn the alphabetical tie rule into Z to A, so it isn't what this lesson asks for.
Common mistakes
- Using
key=lenalone and expecting alphabetical order for ties. - Writing
key=(len(word), word)withoutlambda: the key must be a function. - Returning the result of
.sort(), which isNone.
