developer tip

JavaScript에서 단어를 자르지 않고 문자열 단축

copycodes 2020. 9. 17. 08:02
반응형

JavaScript에서 단어를 자르지 않고 문자열 단축


저는 JavaScript에서 문자열 조작을 잘하지 못합니다. 그리고 어떤 단어도 자르지 않고 문자열을 줄이는 방법이 궁금합니다. 나는 부분 문자열을 사용하는 방법을 알고 있지만 indexOf 또는 아무것도 잘하지 않습니다.

다음 문자열이 있다고 가정하십시오.

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

10 자로 잘라 내고 싶지만 공백으로 끝나지 않으면 단어를 완성하세요. 문자열 변수가 다음과 같이 보이기를 원하지 않습니다.

"이것은 내가 표시 할 수없는 긴 문자열입니다"

공백이 생길 때까지 단어를 끝내고 싶습니다.


내가 올바르게 이해했다면 문자열을 특정 길이로 줄이려고 "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(" ")))

이를 수행하는 방법은 여러 가지가 있지만 정규 표현식은 유용한 한 줄 방법입니다.

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

이 표현식은 처음 11 자 (임의)와 이후 공백이 아닌 문자를 모두 반환합니다.

예제 스크립트 :

<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

나는 이와 같은 간단한 문제에 대해 읽기 어려운 답변이 너무 많고 선택한 답변을 포함한 일부 답변이 작동하지 않는다는 사실에 다소 놀랐습니다.

일반적으로 결과 문자열 은 최대 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"

모든 사람은 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
*/

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

일부 코너 케이스를 처리하지 않는 NT3RP 답변을 기반으로이 코드를 만들었습니다. ...끝에 줄임표 가 추가 된 크기> 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'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;
}

이것이 당신을 괴롭히는 경우 jquery 종속성을 쉽게 제거 할 수 있다고 생각합니다.


나는 다른 접근 방식을 취했습니다. 비슷한 결과가 필요했지만 반환 값을 지정된 길이보다 작게 유지하고 싶었습니다.

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 Example . 연결하는 대신 원래 배열에 다시 결합합니다.

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

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"


최종 단어를 포함하는 대신 제외합니다.

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

나는 파티에 늦었지만 여기에 많은 단어를 반환하기 위해 생각 해낸 작고 쉬운 해결책이 있습니다.

캐릭터 요구 사항과 직접 관련이 없지만 내가 추구 했던 것과 동일한 결과제공합니다 .

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/ 에서 작업 예제를 참조하십시오.


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


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 = "이것은 긴 문자열이며 모든 것을 설명 할 수 없습니다."; 단축 (s, 10, '...')

/* "이것은 .." */


여기에 구두점을 따라 잘리는 또 다른 코드가 있습니다 (이를 찾고 있었고 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

다음과 같이 공간을 다듬을 수 있습니다.

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

문자열 끝에 구두점이나 공백을 남기지 않고 단어 경계로 자르기 위해 이것을 썼을 가치가 있습니다.

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


투표 된 솔루션이 만족스럽지 않았습니다. 그래서 나는 일종의 일반적이고 텍스트의 첫 부분과 마지막 부분 (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;
    }

I came late for this but I think this function makes exactly what OP requests. You can easily change the SENTENCE and the LIMIT values for different results.

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

The output of this snippet is where the LIMIT is 11 is:

[ '[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' ]

With boundary conditions like empty sentence and very long first word. Also, it uses no language specific string 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));


Here is a solution in one line.

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


Updated from @NT3RP I found that if the string happens to hit a space first time around it will end up deleting that word making your string one word shorter than it can be. So I just threw in an if else statement to check that the maxLength doesn't fall on a space.

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)

참고URL : https://stackoverflow.com/questions/5454235/shorten-string-without-cutting-words-in-javascript

반응형