Ceylon 386 333 252 230 222 216 171 153 131 111
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Ungolfed Original:
String truncate(String text, Integer length) {
if(text.size < length) {
return text;
}
Boolean spacePredicate(Character char) {
return char == ' ' || char == '-';
}
Integer? spaceIndex = text[0:length-2].lastIndexWhere(spacePredicate);
if(exists spaceIndex) {
return text[0:spaceIndex] + "...";
}
return text[0:length-3]+"...";
}
Dies sind 386 Bytes / Zeichen. Einige interessante Features hier:
Die x[y:z]Syntax ist syntaktischer Zucker für x.measure(y, z)und gibt einen Unterbereich von xbeginnend ymit Länge zurück z- für Zeichenfolgen ist dies eine Teilzeichenfolge. (Es gibt auch x[y..z]Syntax, die eine ist Spanne von Index y bis z, beide eingeschlossen, wie auch halboffene Spannweiten x[...z]und x[y...].)
List.lastIndexWhereNimmt ein Prädikat (dh eine Funktion, die ein Listenelement nimmt und einen Booleschen Wert zurückgibt, dh hier a Callable<Boolean, [Character]>) und gibt den Index des letzten Listenelements an, in dem das Prädikat erfüllt ist (oder null, wenn es nie erfüllt ist). Da Strings Listen sind, funktioniert dies auch für Strings.
Das Ergebnis spaceIndexist vom Typ Integer|Nulloder Integer?kurz - dh es kann entweder eine Ganzzahl oder null(der einzige Wert von Typ Null) sein. (Der Name spaceIndexstammt aus der Zeit, als ich nicht wusste, dass -das auch etwas Besonderes ist - ich denke, es breakIndexwäre besser.)
Mit können exists spaceIndexwir überprüfen, ob spaceIndexnicht null ist, und dann etwas anderes tun. (In diesem if-Block weiß der Compiler, dass er nicht null ist ... ohne dass er sich beschwert hätte, wenn ich spaceIndexauf den String zugegriffen hätte.)
Anstelle der lokalen Funktion können spacePredicatewir auch eine anonyme Funktion verwenden
(Character char) => char == ' ' || char == '-'
Dies bringt uns auf 333 Zeichen:
String truncate(String text, Integer length) {
if(text.size < length) {
return text;
}
Integer? spaceIndex = text[0:length-2].lastIndexWhere(
(Character char) => char == ' ' || char == '-');
if(exists spaceIndex) {
return text[0:spaceIndex] + "...";
}
return text[0:length-3]+"...";
}
Die nächste Optimierung besteht darin, kürzere Variablen- und Funktionsnamen zu verwenden, was uns um 81 Bytes auf 252 reduziert:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
Integer? i = s[0:l-2].lastIndexWhere(
(Character e) => e == ' ' || e == '-');
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Für die Prädikatfunktion muss tatsächlich kein Argumenttyp deklariert sein, der vom Compiler abgeleitet werden kann. Gleiches gilt für die Art von i(wo wir noch schreiben müssen value, um es als Deklaration zu kennzeichnen). Diese Erklärung ist jetzt kurz genug, um in eine Zeile zu passen, und bringt uns auf 230:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere((e) => e == ' ' || e == '-');
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Anstelle von können e == ' ' || e == '-'wir auch schreiben e in [' ', '-'](oder e in {' ', '-'}, dies ist ein iterierbarer Konstruktor anstelle eines Tupels). Der inOperator ordnet der Methode Category.contains zu, was uns auf die Idee bringt, dass wir die containsMethode dieses Tupels direkt übergeben können (es ist ein aufrufbares Objekt, das ein beliebiges Objekt annimmt, also auch Zeichen akzeptiert), ohne das (e) => ...Boilerplate (222 Bytes):
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere([' ', '-'].contains);
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Eine andere Kategorie, die dieselben zwei Zeichen enthält, ist die aus zwei Zeichen bestehende Zeichenfolge " -". (Außerdem enthält es auch seine Teilzeichenfolgen, aber das tut hier nicht weh). 216 Bytes.
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere(" -".contains);
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Ich denke, wir haben das Beste aus dieser Zeile herausgeholt, wenden wir uns den anderen zu ... Die letzten beiden return-Anweisungen haben eine Ähnlichkeit, die wir ausnutzen können - sie unterscheiden sich nur in ivs. l-3und verwenden inur, wenn sie nicht null sind l-3. Zum Glück ist das genau das, wofür der elseBediener gemacht ist!
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere(" -".contains);
return s[0:(i else l-3)] + "...";
}
(Die Klammern scheinen hier erforderlich zu sein, da elsesie eine niedrigere Priorität haben als [:].) Dies sind 171 Zeichen. Jetzt iwird es nur einmal verwendet, damit wir es einbinden können, sodass wir 153 Zeichen haben:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Wir können diese if-return-returnKombination auch durch eine Kombination der Operatoren thenund elsein einem ersetzen return. ( thenGibt den zweiten Operanden zurück, wenn der erste wahr ist, andernfalls null, wodurch elseder zweite Operand zurückgegeben werden kann.) 131 Bytes (obwohl einige der Einsparungen die Leerzeichen sind, die wir sowieso beseitigen werden):
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Eine Funktion, die nur einen Rücksprung mit einem Ausdruck enthält, kann alternativ mit der "Fettpfeil" -Notation geschrieben werden, die 123 ergibt:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
Durch Entfernen des nicht benötigten Leerzeichens erhalten wir die letzten 111 Bytes:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Zusätzlich gibt es hier eine Funktion, die die Beispiele aus der Frage druckt (unter Verwendung des Namens, tder nach Schritt zwei verwendet wird):
shared void testTruncate() {
value testInputs = {
["This is some very long text.", 25],
["This-is-some-long-hyphen-separated-text.", 33],
["Programming Puzzles & Code Golf is a question and answer site for programming puzzle enthusiasts and code golfers.", 55],
["abcdefghijklmnopqrstuvwxyz", 20],
["a b c", 4],
["Very long.", 100]
};
for(input in testInputs) {
print(t(*input));
}
}