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 Orijinal:
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]+"...";
}
Bu 386 bayt / karakterdir. Burada bazı ilginç özellikler:
x[y:z]Sözdizimi için sözdizimsel şeker x.measure(y, z)ve bir subrange döndürür xbaşlayan yuzunluktaki z- dizeleri, bu bir alt dize olduğunu. (Orada da x[y..z]a, sözdizimi, yayılma z endeksi y ile ilgili, her ikisi de dahil, hem de yarı açık açıklıklar x[...z]ve x[y...].)
List.lastIndexWherebir yüklem alır (yani bir liste öğesini alan ve bir boole döndüren bir işlev, yani burada a Callable<Boolean, [Character]>) ve yüklemin yerine getirildiği son liste öğesinin indeksini verir (veya hiçbir zaman yerine getirilmezse boş). Dizeler liste olduğundan, bu dizeler için de geçerlidir.
Bunun sonucu spaceIndextürdür Integer|Nullya da Integer?kısaca - yani bir Tamsayı ya da null(türün tek değeri Null) olabilir. (Adı spaceIndex, -bunun da özel olduğunu anlamadığımda geliyor - sanırım breakIndexdaha iyi olurdu.)
İle exists spaceIndexbiz kontrol edebilirsiniz spaceIndexboş olmayan ve daha sonra farklı bir şey yapmak. (Bu if-block içerisinde derleyici boş olmadığını biliyor ... spaceIndexdizeye girersem şikayet etmezdi .)
Yerel işlev yerine spacePredicateanonim bir işlev de kullanabiliriz
(Character char) => char == ' ' || char == '-'
Bu bizi 333 karaktere getiriyor:
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]+"...";
}
Bir sonraki optimizasyon, bizi 81 bayttan 252'ye düşüren daha kısa değişken ve fonksiyon adlarını kullanmaktır:
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]+"...";
}
Kestirim işlevi aslında, derleyici tarafından çıkarılan argüman türüne gerek duymaz. Türü için de geçerlidir i( valuebeyanname olarak işaretlemek için hala yazmak zorunda olduğumuz yer ). Şimdi bu bildirim bir çizgiye sığacak kadar kısa ve bizi 230'a indirdi:
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]+"...";
}
Bunun yerine e == ' ' || e == '-'biz de yazabiliriz e in [' ', '-'](veya e in {' ', '-'}bu, bir tuple yerine yinelenebilir bir kurucu). inOperatör o demetin geçebilir fikrine bizi yönteme Category.contains, eşleştiren containsolmadan, (o kadar da karakteri kabul, herhangi bir nesne alarak bir çağrılabilir) doğrudan yöntemi (e) => ...boilerplate (222 bayt):
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]+"...";
}
Aslında, aynı iki karakteri içeren başka bir kategori iki karakterli dizedir " -". (Ayrıca alt dizelerini de içeriyor, ancak burası acı vermiyor). 216 bayt.
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]+"...";
}
Bence, başkalarına sırası izin bu hattın en out var galiba ... Son iki dönüş ifadeleri Elimizde kullanabileceğimiz bazı benzerlikler var - onlar sadece farklılık ivs l-3, ve kullanan vardır io boş değil sadece, aksi takdirde l-3. Neyse ki bu tam olarak elseoperatörün yaptığı şey!
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)] + "...";
}
(Parantezden elsedaha küçük önceliğe sahip olduğu için burada gerekli gibi görünüyor [:].) Bu 171 karakter. Şimdi isadece bir kez kullanılır, bu yüzden satır içi yapabiliriz, bizi 153 karaktere getirir:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Bu if-return-returnkombinasyonu bir arada bulunan thenve elseoperatörlerin bir kombinasyonu ile de değiştirebiliriz.return . ( thenbirincisi doğru olduğunda elseikinci işlenendir , aksi takdirde null olur, o zaman ikinci işleyicisini döndürür .`) 131 bayt (tasarrufların bazıları yine de kurtulacağımız beyaz boşluklar olsa da):
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Bir ifadeyle yalnızca bir dönüş içeren bir işlev, alternatif olarak "şişman ok" gösterimi ile yazılabilir, 123:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
Gereksiz boşlukların kaldırılması bize son 111 baytı verir:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Ek olarak, burada sorudan örnekleri basan bir işlev ( tikinci adımdan sonra kullanılan adı kullanarak ):
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));
}
}