Persingkat string tanpa memotong kata-kata dalam JavaScript

102

Saya tidak pandai memanipulasi string di JavaScript, dan saya bertanya-tanya bagaimana Anda akan mempersingkat string tanpa memotong kata apa pun. Saya tahu cara menggunakan substring, tetapi tidak dengan indexOf atau apa pun dengan sangat baik.

Katakanlah saya memiliki string berikut:

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

Saya ingin memangkasnya menjadi 10 karakter, tetapi jika tidak diakhiri dengan spasi, selesaikan kata. Saya tidak ingin variabel string terlihat seperti ini:

"ini adalah string panjang yang tidak bisa aku lepaskan"

Saya ingin menyelesaikan kata sampai spasi muncul.

Josh Bedo
sumber
maksudmu memangkas tali? coba" too many spaces ".trim()
Anurag
1
Beberapa contoh masukan dan keluaran yang diharapkan akan banyak membantu dalam menjawab pertanyaan ini.
menipu
oke maaf bilang saya punya string text = "ini adalah string panjang saya tidak bisa menampilkan" saya ingin memangkasnya menjadi 10 karakter tetapi jika tidak diakhiri dengan spasi, selesaikan kata saya tidak ingin variabel string terlihat seperti ini "ini adalah string panjang yang tidak bisa saya lepaskan"
Josh Bedo

Jawaban:

180

Jika saya mengerti dengan benar, Anda ingin memperpendek string dengan panjang tertentu (mis. Memperpendek "The quick brown fox jumps over the lazy dog" menjadi, katakanlah, 6 karakter tanpa memotong kata apa pun).

Jika ini masalahnya, Anda dapat mencoba sesuatu seperti berikut:

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 and re-trim only when necessary (prevent re-trim when string is shorted than maxLength, it causes last word cut) 
if(yourString.length > trimmedString.length){
    //trim the string to the maximum length
    var trimmedString = yourString.substr(0, maxLength);

    //re-trim if we are in the middle of a word and 
    trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")))
}
NT3RP
sumber
9
@ Astaga sama sekali tidak benar bahwa ".replace" tidak berfungsi di "fungsi jQuery". Bahkan tidak ada yang namanya "fungsi jQuery".
Pointy
3
bukankah itu harus "maxLength + 1". Dan jika maxLength lebih besar atau sama dari panjang kalimat lengkap, dari kata terakhir tidak disertakan. tapi terima kasih atas solusinya.
Beytan Kurt
4
Jika menggunakan ini pada string yang lebih pendek dari maxLength, kata terakhir akan terpotong. Mungkin @AndrewJuniorHoward sudah menyatakan perbaikan untuk ini ( maxLength + 1), tetapi saya memperbaikinya hanya dengan menambahkan baris ini di bagian atas:var yourString += " ";
tylerl
3
Sayangnya, jika Anda mengambil fox jumps over the lazy dogbagian, hasilnya akan The quick brown seperti yang seharusnya The quick brown fox.
Andrey Gordeev
2
Ini selalu memotong kata terakhir.
Chris Cinelli
108

Ada banyak cara untuk melakukannya, tetapi ekspresi reguler adalah metode satu baris yang berguna:

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

Ekspresi ini mengembalikan 11 karakter pertama (apa saja) ditambah karakter non-spasi berikutnya.

Contoh skrip:

<pre>
<script>
var t = "this is a longish string of text";

document.write("1:   " + t.replace(/^(.{1}[^\s]*).*/, "$1") + "\n");
document.write("2:   " + t.replace(/^(.{2}[^\s]*).*/, "$1") + "\n");
document.write("5:   " + t.replace(/^(.{5}[^\s]*).*/, "$1") + "\n");
document.write("11:  " + t.replace(/^(.{11}[^\s]*).*/, "$1") + "\n");
document.write("20:  " + t.replace(/^(.{20}[^\s]*).*/, "$1") + "\n");
document.write("100: " + t.replace(/^(.{100}[^\s]*).*/, "$1") + "\n");
</script>

Keluaran:

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
Hamish
sumber
Luar biasa, saya benar-benar mencari di Google pertanyaan ini sejuta cara dan hanya dapat menemukan versi yang berfungsi untuk php tidak ada yang mendekati ini dan melibatkan loop.
Josh Bedo
1
Ini mengacu pada kecocokan sub ekspresi pertama (dan hanya, dalam kasus ini) - hal-hal dalam tanda kurung. $ 0 akan merujuk ke keseluruhan pertandingan, yang dalam hal ini adalah keseluruhan string.
Hamish
3
@josh Anda harus dapat membuat panjang maksimum variabel dengan menggunakan objek regexp:t.replace(new RegExp("^(.{"+length+"}[^\s]*).*"), "$1")
rjmackay
1
@Hamish opsi Anda berfungsi dengan baik, tetapi itu termasuk kata terakhir juga jika panjangnya melebihi. Saya mencoba mengubah ekspresi regex untuk mengecualikan kata terakhir jika batas kata maks melebihi tetapi tidak membuatnya berfungsi. Bagaimana kita bisa mencapai itu?
Shashank Agrawal
1
Nah, ini tidak benar-benar berfungsi dengan benar, kadang-kadang saya memberikan nilai maksimum seperti misalnya jika kata terakhir sudah 30 karakter maka akan menjadi dengan panjang lebih dari 60! bahkan jika ditetapkan panjangnya menjadi{30}
Al-Mothafar
65

Saya agak terkejut bahwa untuk soal sederhana seperti ini banyak sekali jawaban yang sulit untuk dibaca dan beberapa, termasuk yang terpilih, tidak berhasil.

Saya biasanya ingin string hasil paling banyak maxLen karakter. Saya juga menggunakan fungsi yang sama ini untuk mempersingkat siput di URL.

str.lastIndexOf(searchValue[, fromIndex]) mengambil parameter kedua yaitu indeks di mana untuk mulai mencari mundur dalam string membuat semuanya efisien dan sederhana.

// 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));
}

Ini adalah contoh keluaran:

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"

Dan untuk siput:

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"
Chris Cinelli
sumber
1
Saya benar-benar lupa tentang lastIndexOf (). Tangkapan yang bagus!
Tici
2
Ini crash jika untuk beberapa alasan stradalah undefined. Saya menambahkanif (!str || str.length <= maxLen) return str;
Silvain
ini tidak menangani kasus tepi di mana pemisah tidak terjadi dalam string
shrewquest
@shrewquest Berhasil. Jika pemisah tidak ada dalam string, ia mengembalikan string itu sendiri jika str.length <= maxLen. Jika tidak, ia mengembalikan string kosong.
Chris Cinelli
20

Semua orang sepertinya lupa bahwa indexOf membutuhkan dua argumen- string untuk dicocokkan, dan indeks karakter untuk mulai mencari. Anda dapat memutuskan string di spasi pertama setelah 10 karakter.

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
*/
kennebec
sumber
Perhatikan bahwa indexOf dapat diganti dengan lastIndexOf jika diperlukan batasan tegas.
Scheintod
14

Lodash memiliki fungsi yang khusus ditulis untuk ini: _.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...'
Leon Li
sumber
7

Berdasarkan jawaban NT3RP yang tidak menangani beberapa kasus sudut, saya telah membuat kode ini. Ini menjamin untuk tidak mengembalikan teks dengan event size> maxLength, elipsis ...ditambahkan di akhir.

Ini juga menangani beberapa kasus sudut seperti teks yang memiliki satu kata menjadi> 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;
}

Saya kira Anda dapat dengan mudah menghapus ketergantungan jquery jika ini mengganggu Anda.

Sebastien Lorber
sumber
3
Saya suka solusi ini, tetapi bukankah argumen yang diberikan $.extendharus dibalik?
JKesMc9tqIQe9M
6

Inilah solusi dalam satu baris.

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

function shorten(text,max) {
    return text && text.length > max ? text.slice(0,max).split(' ').slice(0, -1).join(' ') : text
}


console.log(shorten(text,10));

Joakim Poromaa Helger
sumber
3

Saya terlambat ke pesta, tetapi berikut adalah solusi kecil dan mudah yang saya buat untuk mengembalikan sejumlah kata.

Ini tidak secara langsung terkait dengan kebutuhan karakter Anda , tetapi melayani hasil yang sama seperti yang saya yakin Anda kejar.

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, '...'));

Lihat contoh yang berfungsi di sini: https://jsfiddle.net/bx7rojgL/

Michael Giovanni Pumo
sumber
Anda menulis fungsi JS yang memotong string menjadi sejumlah kata. Baca pertanyaannya lagi.
ChristoKiwi
1
eeehm. Saya pikir ini adalah satu-satunya jawaban yang tepat untuk pertanyaan itu. Dia bertanya tanpa memotong kata.
Mike Aron
2

Ini mengecualikan kata terakhir alih-alih menyertakannya.

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;
}

Pemakaian:

smartTrim(yourString, 11, ' ', ' ...')
"The quick ..."
iklim
sumber
2

Saya mengambil pendekatan yang berbeda. Meskipun saya membutuhkan hasil yang serupa, saya ingin menjaga nilai pengembalian saya kurang dari panjang yang ditentukan.

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 || '');
}

Sunting Saya merefaktornya sedikit di sini: Contoh JSFiddle . Ini bergabung kembali dengan array asli alih-alih menggabungkan.

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 || '');
}
Pete
sumber
2
function shorten(str,n) {
  return (str.match(RegExp(".{"+n+"}\\S*"))||[str])[0];
}

shorten("Hello World", 3); // "Hello"

Roko C. Buljan
sumber
1

Anda dapat menggunakan truncatesatu baris di bawah ini:

const text = "The string that I want to truncate!";

const truncate = (str, len) => str.substring(0, (str + ' ').lastIndexOf(' ', len));

console.log(truncate(text, 14));

Viktor Vlasenko
sumber
1
shorten(str, maxLen, appendix, separator = ' ') {
if (str.length <= maxLen) return str;
let strNope = str.substr(0, str.lastIndexOf(separator, maxLen));
return (strNope += appendix);

}

var s = "ini adalah string yang panjang dan saya tidak bisa menjelaskan semuanya"; persingkat (s, 10, '...')

/* "ini adalah .." */

vivi margaretha
sumber
1

Ini adalah potongan kode lain yang terpotong di sepanjang tanda baca (sedang mencari ini dan Google menemukan pertanyaan ini di sini). Harus menemukan solusi sendiri, jadi inilah yang saya retas dalam 15 menit. Menemukan semua kemunculan. ! ? dan memotong di setiap posisi ini yang <darilen

function pos(str, char) {
    let pos = 0
    const ret = []
    while ( (pos = str.indexOf(char, pos + 1)) != -1) {
        ret.push(pos)
    }
    return ret
}

function truncate(str, len) {
    if (str.length < len)
        return str

    const allPos = [  ...pos(str, '!'), ...pos(str, '.'), ...pos(str, '?')].sort( (a,b) => a-b )
    if (allPos.length === 0) {
        return str.substr(0, len)
    }

    for(let i = 0; i < allPos.length; i++) {
        if (allPos[i] > len) {
            return str.substr(0, allPos[i-1] + 1)
        }
    }
}

module.exports = truncate
Stefan
sumber
1

Ketikan, dan dengan elipsis :)

export const sliceByWord = (phrase: string, length: number, skipEllipses?: boolean): string => {
  if (phrase.length < length) return phrase
  else {
    let trimmed = phrase.slice(0, length)
    trimmed = trimmed.slice(0, Math.min(trimmed.length, trimmed.lastIndexOf(' ')))
    return skipEllipses ? trimmed : trimmed + '…'
  }
}
doublejosh
sumber
0

Untuk apa itu layak saya menulis ini untuk memotong ke batas kata tanpa meninggalkan tanda baca atau spasi di akhir string:

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 ? '&hellip;' : '';

    return(str + ellipsis);
}

var testString = "hi stack overflow, how are you? Spare";
var i = testString.length;

document.write('<strong>Without ellipsis:</strong><br>');

while(i > 0)
{
  document.write(i+': "'+ truncateStringToWord(testString, i) +'"<br>');
  i--;
}

document.write('<strong>With ellipsis:</strong><br>');

i = testString.length;
while(i > 0)
{
  document.write(i+': "'+ truncateStringToWord(testString, i, true) +'"<br>');
  i--;
}

bbeckford.dll
sumber
0

Tidak menemukan solusi yang dipilih memuaskan. Jadi saya menulis sesuatu yang agak umum dan berfungsi baik bagian pertama dan terakhir teks Anda (seperti substr tetapi untuk kata-kata). Anda juga dapat mengatur apakah Anda ingin spasi ditinggalkan dalam hitungan karakter.

    function chopTxtMinMax(txt, firstChar, lastChar=0){
        var wordsArr = txt.split(" ");
        var newWordsArr = [];

        var totalIteratedChars = 0;
        var inclSpacesCount = true;

        for(var wordIndx in wordsArr){
            totalIteratedChars += wordsArr[wordIndx].length + (inclSpacesCount ? 1 : 0);
            if(totalIteratedChars >= firstChar && (totalIteratedChars <= lastChar || lastChar==0)){
                newWordsArr.push(wordsArr[wordIndx]);
            }
        }

        txt = newWordsArr.join(" ");
        return txt;
    }
Vasili Paspalas
sumber
0

Saya datang terlambat untuk ini tetapi saya pikir fungsi ini membuat persis apa yang diminta OP. Anda dapat dengan mudah mengubah nilai KALIMAT dan LIMIT untuk hasil yang berbeda.

function breakSentence(word, limit) {
  const queue = word.split(' ');
  const list = [];

  while (queue.length) {
    const word = queue.shift();

    if (word.length >= limit) {
      list.push(word)
    }
    else {
      let words = word;

      while (true) {
        if (!queue.length ||
            words.length > limit ||
            words.length + queue[0].length + 1 > limit) {
          break;
        }

        words += ' ' + queue.shift();
      }

      list.push(words);
    }
  }

  return list;
}

const SENTENCE = 'the quick brown fox jumped over the lazy dog';
const LIMIT = 11;

// get result
const words = breakSentence(SENTENCE, LIMIT);

// transform the string so the result is easier to understand
const wordsWithLengths = words.map((item) => {
  return `[${item}] has a length of - ${item.length}`;
});

console.log(wordsWithLengths);

Output dari cuplikan ini adalah dengan LIMITnya 11 adalah:

[ '[the quick] has a length of - 9',
  '[brown fox] has a length of - 9',
  '[jumped over] has a length of - 11',
  '[the lazy] has a length of - 8',
  '[dog] has a length of - 3' ]
Ian Calderon
sumber
0

Dengan syarat batas seperti kalimat kosong dan kata pertama sangat panjang. Juga, ia tidak menggunakan api / perpustakaan string khusus bahasa.

function solution(message, k) {
    if(!message){
        return ""; //when message is empty
    }
    const messageWords = message.split(" ");
    let result = messageWords[0];
    if(result.length>k){
        return ""; //when length of first word itself is greater that k
    }
    for(let i = 1; i<messageWords.length; i++){
        let next = result + " " + messageWords[i];

        if(next.length<=k){
            result = next;
        }else{
            break;
        }
    }
    return result;
}

console.log(solution("this is a long string i cant display", 10));

Shishir Arora
sumber
0

'Pasta dengan tomat dan bayam'

jika Anda tidak ingin memotong kata menjadi dua

iterasi pertama:

acc: 0 / acc + cur.length = 5 / newTitle = ['Pasta'];

iterasi kedua:

acc: 5 / acc + cur.length = 9 / newTitle = ['Pasta', 'with'];

iterasi ketiga:

acc: 9 / acc + cur.length = 15 / newTitle = ['Pasta', 'with', 'tomato'];

iterasi keempat:

acc: 15 / acc + cur.length = 18 (batas terikat) / newTitle = ['Pasta', 'with', 'tomato'];

const limitRecipeTitle = (title, limit=17)=>{
    const newTitle = [];
    if(title.length>limit){
        title.split(' ').reduce((acc, cur)=>{
            if(acc+cur.length <= limit){
                newTitle.push(cur);
            }
            return acc+cur.length;
        },0);
    }

    return `${newTitle.join(' ')} ...`
}

keluaran: Pasta dengan tomat ...

Tuan
sumber
-1

Anda dapat memangkas spasi dengan ini:

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

Diperbarui dari @ NT3RP Saya menemukan bahwa jika string kebetulan mengenai spasi pertama kali di sekitarnya akan berakhir dengan menghapus kata itu membuat string Anda satu kata lebih pendek dari yang seharusnya. Jadi saya hanya memasukkan pernyataan if else untuk memeriksa bahwa maxLength tidak jatuh pada spasi.

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)
Landon Call
sumber