Inhalt
Die Fakten:
Plattform: | codewars.com |
Name: | Title Case |
Level: | 6 kyu |
Sprache: | JavaScript |
Beschreibung:
A string is considered to be in title case if each word in the string is either (a) capitalised (that is, only the first letter of the word is in upper case) or (b) considered to be an exception and put entirely into lower case unless it is the first word, which is always capitalised.
Write a function that will convert a string into title case, given an optional list of exceptions (minor words). The list of minor words will be given as a string with each word separated by a space. Your function should ignore the case of the minor words string -- it should behave in the same way even if the case of the minor word string is changed.
Arguments (Haskell)
- First argument: space-delimited list of minor words that must always be lowercase except for the first word in the string.
- Second argument: the original string to be converted.
Arguments (Other languages)
- First argument (required): the original string to be converted.
- Second argument (optional): space-delimited list of minor words that must always be lowercase except for the first word in the string. The JavaScript/CoffeeScript tests will pass
undefined
when this argument is unused.
Example
titleCase('a clash of KINGS', 'a an the of') // should return: 'A Clash of Kings'
titleCase('THE WIND IN THE WILLOWS', 'The In') // should return: 'The Wind in the Willows'
titleCase('the quick brown fox') // should return: 'The Quick Brown Fox'
titleCase('a clash of KINGS', 'a an the of') # should return: 'A Clash of Kings'
titleCase('THE WIND IN THE WILLOWS', 'The In') # should return: 'The Wind in the Willows'
titleCase('the quick brown fox') # should return: 'The Quick Brown Fox'
titleCase('a clash of KINGS', 'a an the of') // should return: 'A Clash of Kings'
titleCase('THE WIND IN THE WILLOWS', 'The In') // should return: 'The Wind in the Willows'
titleCase('the quick brown fox') // should return: 'The Quick Brown Fox'
title_case('a clash of KINGS', 'a an the of') # should return: 'A Clash of Kings'
title_case('THE WIND IN THE WILLOWS', 'The In') # should return: 'The Wind in the Willows'
title_case('the quick brown fox') # should return: 'The Quick Brown Fox'
title_case('a clash of KINGS', 'a an the of') # should return: 'A Clash of Kings'
title_case('THE WIND IN THE WILLOWS', 'The In') # should return: 'The Wind in the Willows'
title_case('the quick brown fox') # should return: 'The Quick Brown Fox'
titleCase "a an the of" "a clash of KINGS" -- should return: "A Clash of Kings"
titleCase "The In" "THE WIND IN THE WILLOWS" -- should return: "The Wind in the Willows"
titleCase "" "the quick brown fox" -- should return: "The Quick Brown Fox"
Kata.TitleCase("a clash of KINGS", "a an the of") => "A Clash of Kings"
Kata.TitleCase("THE WIND IN THE WILLOWS", "The In") => "The Wind in the Willows"
Kata.TitleCase("the quick brown fox") => "The Quick Brown Fox"
Quelle: codewars.com
Lösung
Pseudo-Code
Es gibt wie immer viele Varianten, hier ist eine meiner.
Erst die Lösungsschritte in Pseudo-Code. Los geht’s:
Lösungsschritte
Schritt 1
Als Erstes erstellen wir uns eine capitalize()
-Hilfsfunktion.
Schritt 2
Wenn wir keinen Titel haben, können wir direkt den Inhalt des title
-Arguments zurückgeben.
Schritt 3
Wenn wir keine minorWords
haben, können wir einfach einmal durch die Wörter des Titels loopen und alle Wörter kapitalisieren.
Schritt 4
Ansonsten loopen wir durch die Wörter und prüfen ob das aktuelle Wort in minorWords
enthalten ist (und ob es sich um das erste Wort handelt).
Schritt 5
Wenn es enthalten ist, geben wir das aktuelle Wort unverändert zurück. Wenn nicht, kapitalisieren wir es.
Code
Geil. Übersetzen wir unseren Pseudo-Code in JavaScript:
Lösungsschritte
Zuerst die capitalize()
-Hilfsfuntion:
function capitalize(word) {
return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
Und schon geht’s weiter mit der Hauptfunktion.
Die erste Zeile meiner Hauptfunktion:
function titleCase(title, minorWords) {
Dann der Test, ob wir überhaupt einen Titel haben:
if (!title) return title;
Wenn ja, wandeln wir ihn in ein Array um:
const words = title.toLowerCase().split(" ");
Vorsichtshalber wandeln wir hier alle Buchstaben noch in Kleinbuchstaben um.
Wenn wir keine minorWords
haben loopen wir einfach ein Mal durch das Array und kapitalisieren jedes Wort:
if (!minorWords) return words.map((word) => capitalize(word)).join(" ");
Das Ergebnis können wir in diesem Fall direkt wieder in einen String umwandeln und zurückgeben.
Ansonsten machen wir aus den minorWords
auch ein Array:
const minorWordsArr = minorWords.toLowerCase().split(" ");
Auch hier wandeln wir wieder alles in Kleinbuchstaben um.
Dann loopen wir durch die Wörter:
return words
.map((word, i) => {
Hier können wir locker chainen. Darum können wir das return
hier schon hinschreiben. Der Index wird uns gleich noch nützlich sein.
Jetzt prüfen wir, ob das aktuelle Wort in minorWords
(bzw. im Array) enthalten ist:
if (i && minorWordsArr.includes(word)) return word;
Mit dem Index prüfen wir hier, ob es sich um das erste Wort handelt. 0
ist falsy
. D.h., wenn i
gleich 0
ist, wird der Ausdruck false
und damit übersprungen.
Wenn das aktuelle Wort also am Anfang steht oder nicht in minorWords
enthalten ist, geben wir das Wort kapitalisiert zurück:
return capitalize(word);
})
Aus dem Array wieder einen String machen und fertig:
.join(" ");
}
Voilá! 💪
Komplettlösung
function titleCase(title, minorWords) {
if (!title) return title;
const words = title.toLowerCase().split(" ");
if (!minorWords) return words.map((word) => capitalize(word)).join(" ");
const minorWordsArr = minorWords.toLowerCase().split(" ");
return words
.map((word, i) => {
if (i && minorWordsArr.includes(word)) return word;
return capitalize(word);
})
.join(" ");
}
function capitalize(word) {
return word[0].toUpperCase() + word.slice(1).toLowerCase();
}