Подтвердить что ты не робот

Сократить строку без сокращения слов в JavaScript

Я не очень хорошо разбираюсь в строковых манипуляциях в JavaScript, и мне было интересно, как вы собираетесь сокращать строку, не прерывая никаких слов. Я знаю, как использовать подстроку, но не indexOf или что-то действительно хорошее.

Скажем, у меня была следующая строка:

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

Я хочу обрезать его до 10 символов, но если он не заканчивается пробелом, закончите слово. Я не хочу, чтобы строковая переменная выглядела так:

"это длинная строка я can not dis"

Я хочу, чтобы он завершил слово до тех пор, пока не произойдет пробел.

4b9b3361

Ответ 1

Если я правильно понимаю, вы хотите сократить строку до определенной длины (например, сократите "The quick brown fox jumps over the lazy dog" до, скажем, 6 символов, не отрезая ни слова).

Если это так, вы можете попробовать что-то вроде следующего:

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(" ")))

Ответ 2

Существует много способов сделать это, но регулярное выражение - полезный метод с одной строкой:

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

Эти выражения возвращают первые 11 (любых) символов плюс любые последующие непространственные символы.

Пример script:

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

Вывод:

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

Ответ 3

Я удивлен тем, что для простой такой проблемы есть так много ответов, которые трудно читать, а некоторые, в том числе и избранные, не работают.

Обычно я хочу, чтобы в строке результата было не больше символов maxLen. Я также использую эту же функцию для сокращения пули в URL-адресах.

str.lastIndexOf(searchValue[, fromIndex]) принимает второй параметр, который является индексом для начала поиска назад в строке, что делает вещи эффективными и простыми.

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

Это примерный результат:

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"

И для пули:

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"

Ответ 4

Кажется, что все забывают, что indexOf принимает два аргумента - строку для соответствия и индекс символа, с которого нужно начинать искать. Вы можете разбить строку в первом пространстве после 10 символов.

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
*/

Ответ 5

Lodash имеет функцию, специально написанную для этого: _.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...'

Ответ 6

На основании ответа NT3RP, который не обрабатывает некоторые угловые случаи, я сделал этот код. Он гарантирует, что не будет возвращен текст с событием size > maxLength в конце будет добавлен эллипсис ....

Это также обрабатывает некоторые угловые случаи, такие как текст с одним словом > 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 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;
}

Я думаю, вы можете легко удалить зависимость jquery, если это вас беспокоит.

Ответ 7

Я использовал другой подход. Хотя мне нужен был аналогичный результат, я хотел сохранить возвращаемое значение меньше указанной длины.

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

Изменить Я немного переработал его здесь: Пример JSFiddle. Он присоединяется к исходному массиву вместо конкатенации.

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

Ответ 8

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"

Ответ 9

Это исключает заключительное слово вместо его включения.

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

Использование:

smartTrim(yourString, 11, ' ', ' ...')
"The quick ..."

Ответ 10

Я опаздываю на вечеринку, но здесь небольшое и простое решение, которое я придумал, чтобы вернуть несколько слов.

Это не напрямую связано с вашим требованием к символам, но оно служит тому же результату, который, как я полагаю, вам нужно.

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

См. рабочий пример здесь: https://jsfiddle.net/bx7rojgL/

Ответ 11

Вы можете использовать однострочный truncate ниже:

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

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

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

Ответ 12

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 = "это длинная строка, и я не могу объяснить все"; сократить (с, 10, '...')

/* "это.." */

Ответ 13

Вы можете обрезать пробелы следующим образом:

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

Ответ 14

Для чего я написал это, чтобы усечь границу слова, не оставляя пунктуации или пробела в конце строки:

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

Ответ 15

Не нашли удовлетворительные решения, за которые проголосовали. Поэтому я написал что-то общее и работает как с первой, так и с последней частью вашего текста (что-то вроде substr, но для слов). Также вы можете установить, хотите ли вы, чтобы пробелы не учитывались при подсчете символов.

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

Ответ 16

Я опоздал на это, но я думаю, что эта функция делает именно то, что запрашивает OP. Вы можете легко изменить значения SENTENCE и LIMIT для разных результатов.

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

Ответ 17

С граничными условиями, такими как пустое предложение и очень длинное первое слово. Кроме того, он не использует специфичную для языка строку api/library.

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

Ответ 18

Вот еще один фрагмент кода, который усекает знаки препинания (искал это, и Google нашел этот вопрос здесь). Пришлось придумать решение самостоятельно, вот что я взломал за 15 минут. Находит все вхождения. ! ? и усекает в любой позиции из них, что <чем len

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

Ответ 19

Вот решение в одной строке.

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

Ответ 20

Обновлено из @NT3RP. Я обнаружил, что если строка попадает в пространство в первый раз, это приведет к тому, что это слово сделает вашу строку на одно слово короче, чем может быть. Поэтому я просто добавил инструкцию if else, чтобы проверить, что maxLength не попадает в пробел.

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)