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)]+"...";
Asli Tidak Disatukan:
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]+"...";
}
Ini adalah 386 byte / karakter. Beberapa fitur menarik di sini:
The x[y:z]
sintaks sintaksis gula untuk x.measure(y, z)
, dan mengembalikan subrange dari x
mulai y
dengan panjang z
- untuk string, ini adalah substring. (Ada juga x[y..z]
sintaksis, yang merupakan rentang dari indeks y ke z, keduanya inklusif, serta bentang setengah terbuka x[...z]
dan x[y...]
.)
List.lastIndexWhere
mengambil predikat (yaitu fungsi mengambil elemen daftar dan mengembalikan boolean, yaitu di sini a Callable<Boolean, [Character]>
), dan memberikan indeks elemen daftar terakhir tempat predikat terpenuhi (atau nol, jika tidak pernah terpenuhi). Karena string adalah daftar, ini juga berfungsi untuk string.
Hasil dari ini, spaceIndex
adalah tipe Integer|Null
, atau Integer?
untuk pendek - yaitu dapat berupa Integer atau null
(satu-satunya nilai tipe Null
). (Nama itu spaceIndex
berasal dari ketika saya tidak menyadari bahwa -
itu juga istimewa - saya kira breakIndex
akan lebih baik.)
Dengan exists spaceIndex
kita dapat memeriksa apakah spaceIndex
itu nol, dan kemudian melakukan sesuatu yang berbeda. (Di dalam ini jika-blok kompiler tahu bahwa itu bukan nol ... tanpa itu akan mengeluh jika saya digunakan spaceIndex
untuk mengakses string.)
Alih-alih fungsi lokal spacePredicate
kami juga dapat menggunakan fungsi anonim
(Character char) => char == ' ' || char == '-'
Ini membawa kita ke 333 karakter:
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]+"...";
}
Optimalisasi selanjutnya adalah menggunakan nama variabel dan fungsi yang lebih pendek, yang menurunkan kita sebesar 81 byte menjadi 252:
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]+"...";
}
Fungsi predikat sebenarnya tidak perlu tipe argumennya dideklarasikan, yang dapat disimpulkan oleh kompiler. Sama untuk jenis i
(di mana kita masih harus menulis value
untuk menandainya sebagai deklarasi). Sekarang deklarasi itu cukup pendek untuk muat pada satu baris, membawa kita ke 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]+"...";
}
Alih-alih e == ' ' || e == '-'
kita juga dapat menulis e in [' ', '-']
(atau e in {' ', '-'}
, ini adalah konstruktor yang dapat diubah bukan yang tuple). The in
Operator peta dengan metode Category.contains, yang membawa kita ke gagasan bahwa kita dapat melewati bahwa tuple ini contains
metode langsung (itu adalah callable mengambil objek apapun, sehingga juga menerima karakter), tanpa (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]+"...";
}
Sebenarnya, kategori lain yang mengandung dua karakter yang sama adalah string dua karakter " -"
. (Selain itu juga mengandung substringnya, tapi tidak ada salahnya di sini). 216 byte.
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]+"...";
}
Saya kira kita mendapatkan yang terbaik dari baris ini, mari kita beralih ke yang lain ... dua pernyataan pengembalian terakhir memiliki beberapa kesamaan yang dapat kita eksploitasi - mereka hanya berbeda dalam i
vs l-3
, dan menggunakan i
tepat ketika itu bukan nol, jika tidak l-3
. Untungnya inilah yang else
dibuat untuk operator!
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)] + "...";
}
(Kurung tampaknya diperlukan di sini, karena else
memiliki prioritas lebih rendah daripada [:]
.) Ini adalah 171 karakter. Sekarang i
digunakan hanya sekali, jadi kita bisa inline itu, membawa kita ke 153 karakter:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Kami juga dapat mengganti if-return-return
kombinasi ini dengan kombinasi operator then
dan else
dalam satu return
. ( then
pengembalian adalah operan kedua ketika yang pertama benar, jika tidak nol, yang kemudian memungkinkan else
untuk mengembalikan operan kedua.`) 131 byte (meskipun beberapa penghematan adalah ruang putih yang akan kita singkirkan):
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Fungsi yang berisi hanya satu pengembalian dengan ekspresi alternatifnya dapat ditulis dengan notasi "panah gemuk", memberikan 123:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
Menghapus spasi kosong yang tidak dibutuhkan memberi kita 111 byte terakhir:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Sebagai tambahan, berikut adalah fungsi yang mencetak contoh-contoh dari pertanyaan (menggunakan nama t
yang digunakan setelah langkah kedua):
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));
}
}