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 gốc:
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]+"...";
}
Đây là 386 byte / ký tự. Một số tính năng thú vị ở đây:
Các x[y:z]
cú pháp là cú pháp đường cho x.measure(y, z)
, và trả về một subrange của x
khởi điểm y
với chiều dài z
- cho chuỗi, đây là một chuỗi. (Ngoài ra còn có x[y..z]
cú pháp, là một khoảng từ chỉ số y đến z, bao gồm cả, cũng như các nhịp mở nửa x[...z]
và x[y...]
.)
List.lastIndexWhere
lấy một vị ngữ (tức là một hàm lấy một phần tử danh sách và trả về một boolean, tức là ở đây một Callable<Boolean, [Character]>
) và đưa ra chỉ mục của phần tử danh sách cuối cùng trong đó vị từ được hoàn thành (hoặc null, nếu nó không bao giờ được hoàn thành). Vì chuỗi là danh sách, điều này cũng hoạt động cho chuỗi.
Kết quả của việc này, spaceIndex
thuộc loại Integer|Null
hoặc Integer?
viết tắt - nghĩa là nó có thể là Số nguyên hoặc null
(giá trị duy nhất của loại Null
). (Cái tên spaceIndex
này xuất phát từ khi tôi không nhận ra điều đó -
cũng đặc biệt - tôi đoán breakIndex
sẽ tốt hơn.)
Với exists spaceIndex
chúng tôi có thể kiểm tra nếu spaceIndex
không phải là null, và sau đó làm một cái gì đó khác nhau. (Bên trong khối if-trình biên dịch này biết rằng nó không phải là null ... nếu không có nó sẽ phàn nàn nếu tôi sử dụng spaceIndex
để truy cập chuỗi.)
Thay vì chức năng cục bộ, spacePredicate
chúng ta cũng có thể sử dụng một chức năng ẩn danh
(Character char) => char == ' ' || char == '-'
Điều này đưa chúng ta đến 333 ký tự:
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]+"...";
}
Tối ưu hóa tiếp theo là sử dụng các tên hàm và biến ngắn hơn, đưa chúng ta xuống 81 byte xuống còn 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]+"...";
}
Hàm vị ngữ thực sự không cần loại đối số được khai báo, có thể được trình biên dịch suy ra. Tương tự cho loại i
(nơi chúng ta vẫn phải viết value
để đánh dấu nó là một khai báo). Bây giờ tuyên bố đó đủ ngắn để phù hợp với một dòng, đưa chúng tôi xuống 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]+"...";
}
Thay vì e == ' ' || e == '-'
chúng ta cũng có thể viết e in [' ', '-']
(hoặc e in {' ', '-'}
, đây là một hàm tạo có thể lặp lại thay vì một tuple). Các in
nhà khai thác bản đồ với phương pháp Category.contains, mà đưa chúng ta đến ý kiến cho rằng chúng ta có thể vượt qua của tuple rằng contains
phương pháp trực tiếp (nó là một callable dùng bất cứ đối tượng, vì vậy cũng chấp nhận ký tự), mà không (e) => ...
soạn sẵn (222 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]+"...";
}
Trên thực tế, một thể loại khác chứa hai ký tự giống nhau là chuỗi hai ký tự " -"
. (Ngoài ra, nó cũng chứa các chuỗi con của nó, nhưng điều đó không gây hại ở đây). 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]+"...";
}
Tôi đoán rằng chúng tôi đã tận dụng tối đa dòng này, chúng ta hãy chuyển sang các dòng khác ... hai câu trả về cuối cùng có một số điểm tương tự mà chúng ta có thể khai thác - chúng chỉ khác nhau i
so với l-3
và không sử dụng i
khi nó không rỗng, nếu không l-3
. May mắn thay, đây là chính xác những gì các else
nhà điều hành được thực hiện cho!
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)] + "...";
}
(Các dấu ngoặc đơn dường như là cần thiết ở đây, vì else
có độ ưu tiên thấp hơn [:]
.) Đây là 171 ký tự. Bây giờ i
được sử dụng chỉ một lần, vì vậy chúng tôi có thể nội tuyến nó, đưa chúng tôi tới 153 ký tự:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Chúng ta cũng có thể thay thế if-return-return
sự kết hợp này bằng sự kết hợp của các toán tử then
và else
toán tử trong một return
. ( then
trả về là toán hạng thứ hai khi giá trị thứ nhất là đúng, nếu không thì null, sau đó cho phép else
trả về toán hạng thứ hai của nó. ') 131 byte (mặc dù một số khoản tiết kiệm là khoảng trắng mà chúng ta sẽ thoát khỏi mọi cách):
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Một hàm chỉ chứa một trả về với một biểu thức có thể được viết bằng ký hiệu "mũi tên béo", đưa ra 123:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
Xóa khoảng trắng không cần thiết sẽ cho chúng ta 111 byte cuối cùng:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Ngoài ra, đây là một chức năng in các ví dụ từ câu hỏi (sử dụng tên t
được sử dụng sau bước hai):
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));
}
}