Cách thông minh để cắt chuỗi dài


187

Có ai có một giải pháp / thư viện phức tạp hơn để cắt xén chuỗi bằng JavaScript và đặt dấu chấm lửng ở cuối, hơn là giải pháp rõ ràng:

if (string.length > 25) {
  string = string.substring(0, 24) + "...";
}

5
Bạn có ý nghĩa gì bởi "tinh vi hơn"? Chức năng đưa ranh giới từ vào tài khoản?
Residuum

2
Và không cắt ngắn ở giữa các thẻ HTML.
Sz.

Câu trả lời:


366

Về cơ bản, bạn kiểm tra độ dài của chuỗi đã cho. Nếu nó dài hơn một độ dài nhất định n, hãy cắt nó thành chiều dài n( substrhoặc slice) và thêm thực thể html …(Hoài) vào chuỗi đã cắt.

Một phương pháp như vậy

function truncate(str, n){
  return (str.length > n) ? str.substr(0, n-1) + '…' : str;
};

Nếu 'tinh vi hơn', bạn có nghĩa là cắt ngắn ở ranh giới từ cuối cùng của chuỗi thì bạn cần kiểm tra thêm. Trước tiên, bạn cắt chuỗi theo độ dài mong muốn, tiếp theo bạn đưa kết quả của chuỗi đó đến ranh giới từ cuối cùng của nó

function truncate( str, n, useWordBoundary ){
  if (str.length <= n) { return str; }
  const subString = str.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

Bạn có thể mở rộng Stringnguyên mẫu tự nhiên với chức năng của bạn. Trong trường hợp đó, strtham số cần được loại bỏ và strtrong hàm nên được thay thế bằng this:

String.prototype.truncate = String.prototype.truncate || 
function ( n, useWordBoundary ){
  if (this.length <= n) { return this; }
  const subString = this.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

Nhiều nhà phát triển giáo điều có thể khiến bạn mạnh mẽ về điều đó (" Đừng sửa đổi các đối tượng bạn không sở hữu ". Mặc dù vậy tôi cũng không bận tâm lắm).

Một cách tiếp cận mà không mở rộng Stringnguyên mẫu là tạo đối tượng trợ giúp của riêng bạn, chứa chuỗi (dài) mà bạn cung cấp và phương thức đã nói ở trên để cắt bớt nó. Đó là những gì đoạn trích dưới đây làm.

Cuối cùng, bạn chỉ có thể sử dụng css để cắt các chuỗi dài trong các nút HTML. Nó cung cấp cho bạn ít kiểm soát hơn, nhưng cũng có thể là giải pháp khả thi.


5
Cũng nên xem xét việc có giới hạn "cứng" và "mềm", ví dụ như, nếu chuỗi dài hơn 500 ký tự, hãy cắt ngắn nó thành 400. Điều này có thể hữu ích, khi người dùng muốn xem toàn bộ văn bản và nhấp vào một số liên kết cho nó. Nếu, kết quả là, bạn chỉ tải thêm 1 hoặc 2 ký tự, nó sẽ trông rất xấu xí.
Maxim Sloyko

2
Tham số thứ hai substrlà độ dài nên substr(0,n)thay vào đó để giới hạn nó ở nký tự đầu tiên .
JohnnyHK

10
Đừng sửa đổi các đối tượng bạn không sở hữu. nczonline.net/blog/2010/03/02/ khăn
Charlie Kilian

5
Một điều bạn có thể cân nhắc là thay thế &hellip;dấu chấm lửng ( ...) trong ví dụ mã của bạn. Nếu bạn đang cố gắng sử dụng điều này để tương tác với API, bạn sẽ muốn thực thể không phải là HTML ở đó.
AlbertEngelB

1
@RuneJeppesen bạn đúng. Điều chỉnh các phương pháp. Để bảo vệ tôi: câu trả lời có từ 7 năm trước;)
KooiInc

62

Lưu ý rằng điều này chỉ cần được thực hiện cho Firefox.

Tất cả các trình duyệt khác đều hỗ trợ giải pháp CSS (xem bảng hỗ trợ ):

p {
    white-space: nowrap;
    width: 100%;                   /* IE6 needs any width */
    overflow: hidden;              /* "overflow" value must be different from  visible"*/ 
    -o-text-overflow: ellipsis;    /* Opera < 11*/
    text-overflow:    ellipsis;    /* IE, Safari (WebKit), Opera >= 11, FF > 6 */
}

Điều trớ trêu là tôi đã nhận được đoạn mã đó từ Mozilla MDC.


1
mattsnider.com/css/css-opes-truncation-with-ellipsis để làm cho nó hoạt động với FF là tốt.
Neal

Wow đây là một giải pháp hoàn hảo cho Safari di động. Cảm ơn bạn!
samvermette

9
Cách tiếp cận CSS rất tốt. Có thể có một lưu ý, rằng điều này chỉ hoạt động với một dòng văn bản duy nhất (như dự định white-space: nowrap;). Khi nói đến nhiều hơn một dòng bạn bị mắc kẹt với JavaScript.
insertusernamehere

Nó cũng chỉ hoạt động cho toàn bộ yếu tố. Nếu bạn muốn cắt bớt một phần của chuỗi, mà không gói bit bạn muốn cắt ngắn trong một khoảng hoặc phần tử html khác, thì điều này sẽ không hoạt động, ví dụ:Your picture ('some very long picture filename truncated...') has been uploaded.
Chris

1
OP đã hỏi cụ thể về giải pháp javascript
vsync

24

Có những lý do hợp lệ mà mọi người có thể muốn làm điều này trong JavaScript thay vì CSS.

Để cắt ngắn thành 8 ký tự (bao gồm cả dấu chấm lửng) trong JavaScript:

short = long.replace(/(.{7})..+/, "$1&hellip;");

hoặc là

short = long.replace(/(.{7})..+/, "$1…");

Nếu bạn đếm dấu chấm lửng, đây sẽ là 9 ký tự. Nếu bạn cần nó là 8 sau khi cắt, .replace(/^(.{7}).{2,}/, "$1…");thay vào đó hãy sử dụng
Okku

longshortđược bảo lưu như các từ khóa trong tương lai bởi các thông số kỹ thuật ECMAScript cũ hơn (ECMAScript 1 đến 3). Xem MDN: Các từ khóa được bảo lưu trong tương lai theo các tiêu chuẩn cũ hơn
Ricardo


9
('long text to be truncated').replace(/(.{250})..+/, "$1…");

Bằng cách nào đó, mã trên không hoạt động đối với một số loại văn bản được dán hoặc văn bản trong ứng dụng vuejs. Vì vậy, tôi đã sử dụng lodash truncate và bây giờ nó hoạt động tốt.

_.truncate('long text to be truncated', { 'length': 250, 'separator': ' '});

câu trả lời hiện đại tốt đẹp!
ykonda

Tôi sẽ tò mò muốn biết văn bản là gì. Có phải nó sử dụng các ký tự không phải là tiếng Latin?
Adam Leggett

Đó chỉ là một lorem ipsum
Afraz Ahmad

7

Đây là giải pháp của tôi, có một vài cải tiến so với các đề xuất khác:

String.prototype.truncate = function(){
    var re = this.match(/^.{0,25}[\S]*/);
    var l = re[0].length;
    var re = re[0].replace(/\s$/,'');
    if(l < this.length)
        re = re + "&hellip;";
    return re;
}

// "This is a short string".truncate();
"This is a short string"

// "Thisstringismuchlongerthan25characters".truncate();
"Thisstringismuchlongerthan25characters"

// "This string is much longer than 25 characters and has spaces".truncate();
"This string is much longer&hellip;"

Nó:

  • Cắt ngắn trên không gian đầu tiên sau 25 ký tự
  • Mở rộng đối tượng Chuỗi JavaScript, để nó có thể được sử dụng trên (và xâu chuỗi) bất kỳ chuỗi nào.
  • Sẽ cắt chuỗi nếu cắt ngắn dẫn đến một không gian dấu;
  • Sẽ thêm thực thể hellip unicode (dấu chấm lửng) nếu chuỗi bị cắt ngắn hơn 25 ký tự

7

Chức năng tốt nhất tôi đã tìm thấy. Tín dụng cho dấu chấm lửng văn bản .

function textEllipsis(str, maxLength, { side = "end", ellipsis = "..." } = {}) {
  if (str.length > maxLength) {
    switch (side) {
      case "start":
        return ellipsis + str.slice(-(maxLength - ellipsis.length));
      case "end":
      default:
        return str.slice(0, maxLength - ellipsis.length) + ellipsis;
    }
  }
  return str;
}

Ví dụ :

var short = textEllipsis('a very long text', 10);
console.log(short);
// "a very ..."

var short = textEllipsis('a very long text', 10, { side: 'start' });
console.log(short);
// "...ng text"

var short = textEllipsis('a very long text', 10, { textEllipsis: ' END' });
console.log(short);
// "a very END"

5

Tất cả các trình duyệt hiện đại hiện hỗ trợ một giải pháp CSS đơn giản để tự động thêm dấu chấm lửng nếu một dòng văn bản vượt quá chiều rộng có sẵn:

p {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

(Lưu ý rằng điều này đòi hỏi chiều rộng của phần tử phải được giới hạn theo một cách nào đó để có bất kỳ ảnh hưởng nào.)

Dựa trên https://css-tricks.com/snippets/css/truncate-opes-with-ellipsis/ .

Cần lưu ý rằng phương pháp này không giới hạn dựa trên số lượng ký tự. Nó cũng không hoạt động nếu bạn cần cho phép nhiều dòng văn bản.


2
Điều này chỉ hữu ích cho các câu đơn, không có cách nào (cho đến nay tôi biết) để làm một ví dụ đa dòng thông qua CSS.
Hooman Askari

Có cách nào để làm điều này làm dấu chấm lửng ở bên trái thay vì bên phải không?
GreenAsJade

1
@GreenAsJade Tôi tin rằng bạn có thể thực hiện điều đó bằng cách sử dụng text-direction: rtltext-align: left. Xem davidwalsh.name/css-ellipsis-left
Sean the Bean

4

Hầu hết các khung Javascript hiện đại ( JQuery , Prototype , v.v. ) đều có chức năng tiện ích được xử lý theo Chuỗi xử lý việc này.

Đây là một ví dụ trong Prototype:

'Some random text'.truncate(10);
// -> 'Some ra...'

Đây có vẻ như là một trong những chức năng mà bạn muốn người khác xử lý / duy trì. Tôi sẽ để khung xử lý nó, thay vì viết nhiều mã hơn.


8
Tôi không nghĩ jQuery có bất cứ điều gì cho việc này.
alex

2
Underscore.js hiện - _ ('Xin chào thế giới'). Cắt ngắn (5) => 'Xin chào ...' _ ('Xin chào').
Cắt

3
Pure Underscore dường như không có truncate()- bạn có thể cần một tiện ích mở rộng như underscore.opes .
martin

2
Đây hoàn toàn là câu trả lời đúng. Tôi không biết về gạch dưới, nhưng lodash có _.truncchính xác điều này.
leftclickben

2
Tôi nghĩ rằng câu trả lời đúng là sử dụng lodash.trunc hoặc underscore.opes.truncate.
ooolala

2

Có lẽ tôi đã bỏ lỡ một ví dụ về việc ai đó xử lý null, nhưng 3 câu trả lời HÀNG ĐẦU không hiệu quả với tôi khi tôi có null (Chắc chắn tôi nhận ra rằng xử lý lỗi là và hàng triệu thứ khác KHÔNG phải là trách nhiệm của người trả lời câu hỏi, nhưng vì Tôi đã sử dụng một chức năng hiện có cùng với một trong những câu trả lời dấu chấm lửng tuyệt vời mà tôi nghĩ rằng tôi sẽ cung cấp nó cho người khác.

ví dụ

javascript:

news.comments

sử dụng chức năng cắt ngắn

news.comments.trunc(20, true);

Tuy nhiên, trên news.comments là null, điều này sẽ "phá vỡ"

Sau cùng

checkNull(news.comments).trunc(20, true) 

chức năng cắt ngắn lịch sự của KooiInc

String.prototype.trunc =
 function (n, useWordBoundary) {
     console.log(this);
     var isTooLong = this.length > n,
         s_ = isTooLong ? this.substr(0, n - 1) : this;
     s_ = (useWordBoundary && isTooLong) ? s_.substr(0, s_.lastIndexOf(' ')) : s_;
     return isTooLong ? s_ + '&hellip;' : s_;
 };

Trình kiểm tra null đơn giản của tôi (cũng kiểm tra cả chữ "null" theo nghĩa đen (cái này bắt không xác định, "", null, "null", v.v.)

  function checkNull(val) {
      if (val) {
          if (val === "null") {
              return "";
          } else {
              return val;
          }
      } else {
          return "";
      }
  }

Đây là phiên bản sửa đổi - tránh sử dụng nguyên mẫu, kết hợp kiểm tra null trong chức năng và có một số sử dụng thử nghiệm / demo. codepen.io/mahemoff/pen/LGEdzy
mahemoff

Bạn có thấy nguyên mẫu là có vấn đề? Chỉ tò mò
Tom Stickel 8/12/2015

Lý do cho chức năng kiểm tra null riêng biệt của tôi là vì nó thực sự sẽ kiểm tra null, không xác định, NaN, chuỗi rỗng (""), 0, false và "null" Nhưng nói chung tôi thích fx của bạn
Tom Stickel 8/12/2015

1
Đúng, đó là vấn đề về quan điểm và bối cảnh sử dụng, nhưng nguyên mẫu trở nên xấu xí khi bạn làm việc với các thư viện khác vì chúng cũng có thể ghi đè lên điều tương tự. (Hoặc trong một số trường hợp hiếm hoi, một chức năng cùng tên sau này có thể được giới thiệu như một tính năng ngôn ngữ tiêu chuẩn.)
mahemoff

Vâng, tôi đồng ý với bạn
Tom Stickel 8/12/2015

2

Đôi khi tên tệp được đánh số, trong đó chỉ mục có thể ở đầu hoặc cuối. Vì vậy, tôi muốn rút ngắn từ trung tâm của chuỗi:

function stringTruncateFromCenter(str, maxLength) {
    const midChar = "…";      // character to insert into the center of the result
    var left, right;

    if (str.length <= maxLength) return str;

    // length of beginning part      
    left = Math.ceil(maxLength / 2);

    // start index of ending part   
    right = str.length - Math.floor(maxLength / 2) + 1;   

    return str.substr(0, left) + midChar + str.substring(right);
}

Xin lưu ý rằng tôi đã sử dụng ký tự điền ở đây với hơn 1 byte trong UTF-8.



1

Tôi ủng hộ giải pháp của Kooilnc. Giải pháp nhỏ gọn thực sự tốt đẹp. Có một trường hợp cạnh nhỏ mà tôi muốn giải quyết. Nếu ai đó nhập một chuỗi ký tự thực sự dài vì bất kỳ lý do gì, nó sẽ không bị cắt ngắn:

function truncate(str, n, useWordBoundary) {
    var singular, tooLong = str.length > n;
    useWordBoundary = useWordBoundary || true;

    // Edge case where someone enters a ridiculously long string.
    str = tooLong ? str.substr(0, n-1) : str;

    singular = (str.search(/\s/) === -1) ? true : false;
    if(!singular) {
      str = useWordBoundary && tooLong ? str.substr(0, str.lastIndexOf(' ')) : str;
    }

    return  tooLong ? str + '&hellip;' : str;
}

1

Với một Google Googling nhanh chóng tôi đã tìm thấy điều này ... Điều đó có hiệu quả với bạn không?

/**
 * Truncate a string to the given length, breaking at word boundaries and adding an elipsis
 * @param string str String to be truncated
 * @param integer limit Max length of the string
 * @return string
 */
var truncate = function (str, limit) {
    var bits, i;
    if (STR !== typeof str) {
        return '';
    }
    bits = str.split('');
    if (bits.length > limit) {
        for (i = bits.length - 1; i > -1; --i) {
            if (i > limit) {
                bits.length = i;
            }
            else if (' ' === bits[i]) {
                bits.length = i;
                break;
            }
        }
        bits.push('...');
    }
    return bits.join('');
};
// END: truncate

1

Tràn văn bản: dấu chấm lửng là thuộc tính bạn cần. Với điều này và một tràn: được ẩn với một chiều rộng cụ thể, mọi thứ vượt qua sẽ có hiệu ứng ba giai đoạn ở cuối ... Đừng quên thêm khoảng trắng: nowrap hoặc văn bản sẽ được đặt thành nhiều dòng.

.wrap{
  text-overflow: ellipsis
  white-space: nowrap;
  overflow: hidden;
  width:"your desired width";
}
<p class="wrap">The string to be cut</p>

1
Brevity là chấp nhận được, nhưng giải thích đầy đủ hơn là tốt hơn.
Armali

mwilcoxSean the Bean đã đăng giải pháp này.
Andrew Myers

1
Chỉ có thể được sử dụng cho văn bản một dòng
Vally Pepyako

Tràn văn bản: dấu chấm lửng là hoàn hảo !!
zardilior

0

Theo tôi, câu trả lời của c_harm là tốt nhất. Xin lưu ý rằng nếu bạn muốn sử dụng

"My string".truncate(n)

bạn sẽ phải sử dụng một hàm tạo đối tượng regrec chứ không phải bằng chữ. Ngoài ra, bạn sẽ phải thoát khỏi \Skhi chuyển đổi nó.

String.prototype.truncate =
    function(n){
        var p  = new RegExp("^.{0," + n + "}[\\S]*", 'g');
        var re = this.match(p);
        var l  = re[0].length;
        var re = re[0].replace(/\s$/,'');

        if (l < this.length) return re + '&hellip;';
    };

Mỗi nghe nói về bình luận và đặt tên biến thích hợp?
xe đạp

@b wheel mã được sao chép và sửa đổi từ một câu trả lời khác ở trên, không cần phải quá thô lỗ và lén lút.
Matt Fletcher

0

Sử dụng mã sau

 function trancateTitle (title) {
    var length = 10;
    if (title.length > length) {
       title = title.substring(0, length)+'...';
    }
    return title;
}

0

Sửa lỗi giải pháp của Kooilnc:

String.prototype.trunc = String.prototype.trunc ||
  function(n){
      return this.length>n ? this.substr(0,n-1)+'&hellip;' : this.toString();
  };

Điều này trả về giá trị chuỗi thay vì đối tượng String nếu không cần phải cắt bớt.


Điều này không cung cấp một câu trả lời cho câu hỏi. Để phê bình hoặc yêu cầu làm rõ từ một tác giả, hãy để lại nhận xét bên dưới bài đăng của họ - bạn luôn có thể nhận xét về bài đăng của riêng bạn và khi bạn có đủ danh tiếng, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào .
Spencer Wieczorek

Ah tôi thấy sự khác biệt bây giờ. Cảm ơn các tài liệu tham khảo. Tôi đã muốn để lại một bình luận với hy vọng rằng @Kooilnc sẽ nhìn thấy nó, và có thể chỉnh sửa câu trả lời được chấp nhận nếu anh ấy hoặc cô ấy đồng ý, nhưng không có tiếng tăm.
qwales1

0

Gần đây tôi đã phải làm điều này và kết thúc với:

/**
 * Truncate a string over a given length and add ellipsis if necessary
 * @param {string} str - string to be truncated
 * @param {integer} limit - max length of the string before truncating
 * @return {string} truncated string
 */
function truncate(str, limit) {
    return (str.length < limit) ? str : str.substring(0, limit).replace(/\w{3}$/gi, '...');
}

Cảm thấy tốt và sạch sẽ với tôi :)


1
Điều đó có thể làm cho chuỗi 3 ký tự kết quả dài hơn giới hạn.
Hauke

0

Tôi thích sử dụng .slice () Đối số đầu tiên là chỉ mục bắt đầu và thứ hai là chỉ mục kết thúc. Tất cả mọi thứ ở giữa là những gì bạn nhận lại.

var long = "hello there! Good day to ya."
// hello there! Good day to ya.

var short  = long.slice(0, 5)
// hello

0

Một nơi nào đó thông minh: D

//My Huge Huge String
    let tooHugeToHandle = `It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).`
    
//Trim Max Length
 const maxValue = 50
// The barber.
 const TrimMyString = (string, maxLength, start = 0) => {
//Note - `start` is if I want to start after some point of the string
    	if (string.length > maxLength) {
    	let trimmedString = string.substr(start, maxLength)
    	 return (
    	   trimmedString.substr(
    	   start,
    	   Math.min(trimmedString.length,   trimmedString.lastIndexOf(' '))
           ) + ' ...'
         )
       }
    return string
}

console.log(TrimMyString(tooHugeToHandle, maxValue))


-1

Hàm này cũng có thể cắt các phần không gian và từ. (Ví dụ: Mẹ thành Moth ...)

String.prototype.truc= function (length) {
        return this.length>length ? this.substring(0, length) + '&hellip;' : this;
};

sử dụng:

"this is long length text".trunc(10);
"1234567890".trunc(5);

đầu ra:

đây là ...

12345 ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.