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


102

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

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

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

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

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

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


끈을 다듬 으라는 뜻입니까? try" too many spaces ".trim()
Anurag 2011 년

1
일부 예제 입력 및 예상 출력은이 질문에 대한 답변에 많은 도움이됩니다.
deceze

좋아 죄송합니다. 문자열 텍스트 = "이것은 표시 할 수없는 긴 문자열입니다."라고 말하고 10 자까지 잘라 내고 싶지만 공백으로 끝나지 않으면 단어를 마칩니다. 문자열 변수가 다음과 같이 보이기를 원하지 않습니다. 이 "이 긴 문자열 내가 캔트 창피하다"
조쉬 BEDO

답변:


180

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

9
@josh ".replace"가 "jQuery 함수"에서 작동하지 않는다는 것은 사실이 아닙니다. "jQuery 함수"와 같은 것은 없습니다.
Pointy 2011 년

3
그것은 "maxLength + 1"이어야하지 않습니다. 그리고 maxLength가 전체 문장 길이보다 크거나 같으면 마지막 단어가 포함되지 않습니다. 그러나 해결책에 감사드립니다.
Beytan Kurt 2014

4
maxLength보다 짧은 문자열에 이것을 사용하면 마지막 단어가 잘립니다. 아마도 @AndrewJuniorHoward가 이미 이것 ( maxLength + 1)에 대한 수정 사항을 언급 했지만이 줄을 맨 위에 추가하여 수정했습니다.var yourString += " ";
tylerl

3
안타깝게도 fox jumps over the lazy dog일부를 제거하면 결과는 The quick brown , The quick brown fox.
Andrey Gordeev

2
이것은 항상 마지막 단어를 잘라냅니다.
Chris Cinelli 2016

108

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

"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

대단해, 나는 말 그대로이 질문을 백만 가지 방법으로 검색했으며 이것에 가깝고 루프를 포함하는 PHP의 작동 버전 만 찾을 수있었습니다.
Josh Bedo 2011 년

1
첫 번째 (이 경우에만) 하위 표현식 일치를 참조합니다. 대괄호 안에있는 항목입니다. $ 0은 전체 일치를 나타내며이 경우에는 전체 문자열입니다.
Hamish 2011 년

3
@josh regexp 객체를 사용하여 최대 길이를 변수로 만들 수 있어야합니다.t.replace(new RegExp("^(.{"+length+"}[^\s]*).*"), "$1")
rjmackay 2013-08-08

1
@Hamish 옵션은 잘 작동하지만 길이가 초과되면 마지막 단어도 포함됩니다. 최대 단어 제한을 초과하는 경우 마지막 단어를 제외하도록 정규 표현식을 변경하려고 시도했지만 작동하지 않았습니다. 그것을 어떻게 달성 할 수 있습니까?
Shashank Agrawal 2015 년

1
글쎄, 이것은 실제로 제대로 작동하지 않습니다. 예를 들어 마지막 단어가 이미 30 자라면 이미 길이가 60 이상이 될 것이므로 때로는 최대 값을 전달합니다! 그것은 길이가 설정 한 경우에도{30}
알 - Mothafar

65

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

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

1
lastIndexOf ()에 대해 완전히 잊었습니다. 잘 잡아!
Tici

2
이것은 어떤 이유가있는 경우 충돌 str이다 undefined. 나는 추가if (!str || str.length <= maxLen) return str;
Silvain

이것은 문자열에서 구분자가 발생하지 않는 가장자리 케이스를 처리하지 않습니다
shrewquest

@shrewquest 작동합니다. 구분 기호가 문자열에 없으면 str.length <= maxLen. 그렇지 않으면 빈 문자열을 반환합니다.
Chris Cinelli

20

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

하드 경계가 필요한 경우 indexOf는 lastIndexOf로 대체 될 수 있습니다.
Scheintod 2014

14

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

7

일부 코너 케이스를 처리하지 않는 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 종속성을 쉽게 제거 할 수 있다고 생각합니다.


3
이 솔루션이 마음에 들지만 인수 $.extend가 반대로 전달되지 않아야 합니까?
JKesMc9tqIQe9M

6

여기에 한 줄의 솔루션이 있습니다.

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


3

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

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

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


문자열을 여러 단어로 자르는 JS 함수를 작성했습니다. 질문을 다시 읽으십시오.
ChristoKiwi

1
eeehm. 나는 이것이 질문에 대한 유일한 정답이라고 생각합니다. 그는 단어를 자르지 않고 물었다.
Mike Aron

2

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

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

2

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

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

2
function shorten(str,n) {
  return (str.match(RegExp(".{"+n+"}\\S*"))||[str])[0];
}

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


1

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


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

/* "이것은 .." */


1

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

1

Typescript 및 생략 부호 포함 :)

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 + '…'
  }
}

0

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

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


0

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

0

나는 이것을 위해 늦었지만이 기능이 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);

이 스 니펫의 출력은 LIMIT가 11 인 경우입니다.

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

0

빈 문장과 매우 ​​긴 첫 단어와 같은 경계 조건이 있습니다. 또한 언어 별 문자열 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));


0

'토마토와 시금치 파스타'

단어를 반으로 자르고 싶지 않다면

첫 번째 반복 :

acc : 0 / acc + cur.length = 5 / newTitle = [ '파스타'];

두 번째 반복 :

acc : 5 / acc + cur.length = 9 / newTitle = [ '파스타', '함께'];

세 번째 반복 :

acc : 9 / acc + cur.length = 15 / newTitle = [ '파스타', '함께', '토마토'];

네 번째 반복 :

acc : 15 / acc + cur.length = 18 (한계 제한) / 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(' ')} ...`
}

출력 : 토마토 파스타 ...


-1

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

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

-1

@ NT3RP에서 업데이트 한 문자열이 처음에 공백을 치면 해당 단어가 삭제되어 문자열이 가능한 한 단어가 짧아지는 것을 발견했습니다. 그래서 나는 maxLength가 공간에 떨어지지 않는지 확인하기 위해 if else 문을 던졌습니다.

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.