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 x
başlayan y
uzunluktaki 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.lastIndexWhere
bir 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 spaceIndex
türdür Integer|Null
ya 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 breakIndex
daha iyi olurdu.)
İle exists spaceIndex
biz kontrol edebilirsiniz spaceIndex
boş olmayan ve daha sonra farklı bir şey yapmak. (Bu if-block içerisinde derleyici boş olmadığını biliyor ... spaceIndex
dizeye girersem şikayet etmezdi .)
Yerel işlev yerine spacePredicate
anonim 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
( value
beyanname 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). in
Operatör o demetin geçebilir fikrine bizi yönteme Category.contains, eşleştiren contains
olmadan, (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 i
vs l-3
, ve kullanan vardır i
o boş değil sadece, aksi takdirde l-3
. Neyse ki bu tam olarak else
operatö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 else
daha küçük önceliğe sahip olduğu için burada gerekli gibi görünüyor [:]
.) Bu 171 karakter. Şimdi i
sadece 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-return
kombinasyonu bir arada bulunan then
ve else
operatörlerin bir kombinasyonu ile de değiştirebiliriz.return
. ( then
birincisi doğru olduğunda else
ikinci 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 ( t
ikinci 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));
}
}