Accorcia le stringhe senza tagliare le parole in JavaScript

Non sono molto bravo con la manipolazione delle stringhe in JavaScript, e mi chiedevo come si andrebbe ad accorciare una stringa senza tagliare parole. So come usare la sottostringa, ma non indexOf o qualcosa di veramente buono.

Diciamo che ho avuto la seguente stringa:

text = "this is a long string I cant display" 

Voglio ridurlo a 10 caratteri, ma se non finisce con uno spazio, finisci la parola. Non voglio che la variabile stringa assomigli a questo:

“questa è una lunga stringa che non posso”

Voglio che finisca la parola finché non si verifica uno spazio.

Se ho capito bene, vuoi accorciare una corda ad una certa lunghezza (ad es. Accorciare "The quick brown fox jumps over the lazy dog" per dire, 6 caratteri senza interrompere alcuna parola).

Se questo è il caso, puoi provare qualcosa come la seguente:

 var yourString = "The quick brown fox jumps over the lazy dog"; //replace with your string. var maxLength = 6 // maximum number of characters to extract //trim the string to the maximum length var trimmedString = yourString.substr(0, maxLength); //re-trim if we are in the middle of a word trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" "))) 

Esistono molti modi per farlo, ma un’espressione regolare è un utile metodo a una riga:

 "this is a longish string of text".replace(/^(.{11}[^\s]*).*/, "$1"); //"this is a longish" 

Questa espressione restituisce i primi 11 (qualsiasi) carattere più eventuali successivi caratteri non spaziali.

Script di esempio:

 
 

Produzione:

 1: this 2: this 5: this is 11: this is a longish 20: this is a longish string 100: this is a longish string of text 

Sono sorpreso che per un semplice problema come questo ci siano così tante risposte difficili da leggere e alcune, inclusa quella scelta, non funzionano.

Solitamente voglio che la stringa risultante sia al massimo di caratteri maxLen . Io uso anche questa stessa funzione per accorciare gli slug negli URL.

str.lastIndexOf(searchValue[, fromIndex]) prende un secondo parametro che è l’indice in cui iniziare a cercare all’indietro nella stringa rendendo le cose efficienti e semplici.

 // Shorten a string to less than maxLen characters without truncating words. function shorten(str, maxLen, separator = ' ') { if (str.length < = maxLen) return str; return str.substr(0, str.lastIndexOf(separator, maxLen)); } 

Questo è un esempio di output:

 for (var i = 0; i < 50; i += 3) console.log(i, shorten("The quick brown fox jumps over the lazy dog", i)); 0 "" 3 "The" 6 "The" 9 "The quick" 12 "The quick" 15 "The quick brown" 18 "The quick brown" 21 "The quick brown fox" 24 "The quick brown fox" 27 "The quick brown fox jumps" 30 "The quick brown fox jumps over" 33 "The quick brown fox jumps over" 36 "The quick brown fox jumps over the" 39 "The quick brown fox jumps over the lazy" 42 "The quick brown fox jumps over the lazy" 45 "The quick brown fox jumps over the lazy dog" 48 "The quick brown fox jumps over the lazy dog" 

E per la lumaca:

 for (var i = 0; i < 50; i += 10) console.log(i, shorten("the-quick-brown-fox-jumps-over-the-lazy-dog", i, '-')); 0 "" 10 "the-quick" 20 "the-quick-brown-fox" 30 "the-quick-brown-fox-jumps-over" 40 "the-quick-brown-fox-jumps-over-the-lazy" 

Tutti sembrano dimenticare che indexOf accetta due argomenti: la stringa da abbinare e l’indice dei caratteri da cui iniziare a guardare. Puoi rompere la corda nel primo spazio dopo 10 caratteri.

 function cutString(s, n){ var cut= s.indexOf(' ', n); if(cut== -1) return s; return s.substring(0, cut) } var s= "this is a long string i cant display"; cutString(s, 10) /* returned value: (String) this is a long */ 

Lodash ha una funzione specificamente scritta per questo: _.truncate

 const truncate = _.truncate const str = 'The quick brown fox jumps over the lazy dog' truncate(str, { length: 30, // maximum 30 characters separator: /,?\.* +/ // separate by spaces, including preceding commas and periods }) // 'The quick brown fox jumps...' 

Sulla base della risposta NT3RP che non gestisce alcuni casi d’angolo, ho creato questo codice. Garantisce di non restituire un testo con un evento size> maxLength un ellissi ... stato aggiunto alla fine.

Questo gestisce anche alcuni casi d’angolo come un testo che ha una singola parola che è> maxLength

 shorten: function(text,maxLength,options) { if ( text.length < = maxLength ) { return text; } if ( !options ) options = {}; var defaultOptions = { // By default we add an ellipsis at the end suffix: true, suffixString: " ...", // By default we preserve word boundaries preserveWordBoundaries: true, wordSeparator: " " }; $.extend(options, defaultOptions); // Compute suffix to use (eventually add an ellipsis) var suffix = ""; if ( text.length > maxLength && options.suffix) { suffix = options.suffixString; } // Compute the index at which we have to cut the text var maxTextLength = maxLength - suffix.length; var cutIndex; if ( options.preserveWordBoundaries ) { // We use +1 because the extra char is either a space or will be cut anyway // This permits to avoid removing an extra word when there's a space at the maxTextLength index var lastWordSeparatorIndex = text.lastIndexOf(options.wordSeparator, maxTextLength+1); // We include 0 because if have a "very long first word" (size > maxLength), we still don't want to cut it // But just display "...". But in this case the user should probably use preserveWordBoundaries:false... cutIndex = lastWordSeparatorIndex > 0 ? lastWordSeparatorIndex : maxTextLength; } else { cutIndex = maxTextLength; } var newText = text.substr(0,cutIndex); return newText + suffix; } 

Immagino che tu possa facilmente rimuovere la dipendenza da jQuery se questo ti infastidisce.

Ho preso un approccio diverso. Mentre avevo bisogno di un risultato simile, volevo mantenere il mio valore di ritorno inferiore alla lunghezza specificata.

 function wordTrim(value, length, overflowSuffix) { value = value.trim(); if (value.length < = length) return value; var strAry = value.split(' '); var retString = strAry[0]; for (var i = 1; i < strAry.length; i++) { if (retString.length >= length || retString.length + strAry[i].length + 1 > length) break; retString += " " + strAry[i]; } return retString + (overflowSuffix || ''); } 

Modifica L’ ho rifattorizzato un po ‘qui: JSFiddle Example . Si ricongiunge alla matrice originale invece di concatenare.

 function wordTrim(value, length, overflowSuffix) { if (value.length < = length) return value; var strAry = value.split(' '); var retLen = strAry[0].length; for (var i = 1; i < strAry.length; i++) { if(retLen == length || retLen + strAry[i].length + 1 > length) break; retLen+= strAry[i].length + 1 } return strAry.slice(0,i).join(' ') + (overflowSuffix || ''); } 

Questo esclude la parola finale invece di includerla.

 function smartTrim(str, length, delim, appendix) { if (str.length < = length) return str; var trimmedStr = str.substr(0, length+delim.length); var lastDelimIndex = trimmedStr.lastIndexOf(delim); if (lastDelimIndex >= 0) trimmedStr = trimmedStr.substr(0, lastDelimIndex); if (trimmedStr) trimmedStr += appendix; return trimmedStr; } 

Uso:

 smartTrim(yourString, 11, ' ', ' ...') "The quick ..." 
 function shorten(str,n) { return (str.match(RegExp(".{"+n+"}\\S*"))||[str])[0]; } shorten("Hello World", 3); // "Hello" 
 // SHORTEN STRING TO WHOLE WORDS function shorten(s,l) { return (s.match(new RegExp(".{"+l+"}\\S*"))||[s])[0]; } console.log( shorten("The quick brown fox jumps over the lazy dog", 6) ); // "The quick" 

Sono in ritardo per la festa, ma ecco una soluzione piccola e facile che ho trovato per restituire una quantità di parole.

Non è direttamente correlato alla tua esigenza di personaggi , ma serve lo stesso risultato che credo tu stavi cercando.

 function truncateWords(sentence, amount, tail) { const words = sentence.split(' '); if (amount >= words.length) { return sentence; } const truncated = words.slice(0, amount); return `${truncated.join(' ')}${tail}`; } const sentence = 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.'; console.log(truncateWords(sentence, 10, '...')); 

Guarda l’esempio di lavoro qui: https://jsfiddle.net/bx7rojgL/

Puoi tagliare gli spazi con questo:

 var trimmedString = flabbyString.replace(/^\s*(.*)\s*$/, '$1'); 

Per quello che vale, l’ho scritto per troncare al confine delle parole senza lasciare segni di punteggiatura o spazi bianchi alla fine della stringa:

 function truncateStringToWord(str, length, addEllipsis) { if(str.length < = length) { // provided string already short enough return(str); } // cut string down but keep 1 extra character so we can check if a non-word character exists beyond the boundary str = str.substr(0, length+1); // cut any non-whitespace characters off the end of the string if (/[^\s]+$/.test(str)) { str = str.replace(/[^\s]+$/, ""); } // cut any remaining non-word characters str = str.replace(/[^\w]+$/, ""); var ellipsis = addEllipsis && str.length > 0 ? '…' : ''; return(str + ellipsis); } var testString = "hi stack overflow, how are you? Spare"; var i = testString.length; document.write('Without ellipsis:
'); while(i > 0) { document.write(i+': "'+ truncateStringToWord(testString, i) +'"
'); i--; } document.write('With ellipsis:
'); i = testString.length; while(i > 0) { document.write(i+': "'+ truncateStringToWord(testString, i, true) +'"
'); i--; }

Puoi utilizzare truncate one-liner di seguito:

 const text = "The string that I want to truncate!"; const truncate = (str, len) => str.substring(0, (str + ' ').lastIndexOf(' ', len)); console.log(truncate(text, 14)); 

Aggiornato da @ NT3RP, ho scoperto che se la stringa capita di colpire uno spazio per la prima volta, finirà per cancellare quella parola, rendendo la stringa una parola più corta di quanto possa essere. Quindi ho appena lanciato una dichiarazione if if per verificare che la lunghezza massima non cada su uno spazio.

codepen.io

 var yourString = "The quick brown fox jumps over the lazy dog"; //replace with your string. var maxLength = 15 // maximum number of characters to extract if (yourString[maxLength] !== " ") { //trim the string to the maximum length var trimmedString = yourString.substr(0, maxLength); alert(trimmedString) //re-trim if we are in the middle of a word trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" "))) } else { var trimmedString = yourString.substr(0, maxLength); } alert(trimmedString)