JavaScriptでの文字列操作はあまり得意ではありません。Wordを切断せずに文字列を短縮するにはどうすればよいのかと思っていました。私は部分文字列の使用方法を知っていますが、indexOfなどは本当によくわかりません。
次の文字列があるとしましょう:
text = "this is a long string I cant display"
10文字に切り詰めたいのですが、スペースで終わらない場合は、Wordを終了します。文字列変数を次のようにしたくありません。
「これは長い文字列です」
スペースが発生するまでWordを終了させたい。
私が正しく理解している場合、文字列を特定の長さに短縮する必要があります(例:"The quick brown fox jumps over the lazy dog"
、たとえば、Wordを切り捨てずに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(" ")))
それを行う方法はたくさんありますが、正規表現は便利な1行の方法です。
"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])
は、文字列の後方検索を開始するインデックスである2番目のパラメーターを取り、効率的かつ単純にします。
// 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は、一致する文字列と検索を開始する文字インデックスの2つの引数を取ることを誰もが忘れているようです。 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の回答に基づいて、このコードを作成しました。末尾にEllipsis ...
が追加されたsize> maxLengthイベントのテキストを返さないことを保証します。
これは、単一のWordが> 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 || '');
}
Editここで少しリファクタリングしました: 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"
以下の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 = "これは長い文字列であり、すべてを説明することはできません";短縮(10、 '...')
/* "これは .." */
これにより、最終的なWordは含まれなくなります。
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/
句読点(これを探していたので、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行の解決策です。
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));
文字列の末尾に句読点や空白を残さずにWordの境界に切り捨てるためにこれを書いた価値があるのは、次のとおりです。
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('<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--;
}
空の文や非常に長い最初のWordなどの境界条件を使用します。また、言語固有の文字列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));
私はこれに遅れて来ましたが、この関数は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' ]
これでスペースをトリミングできます:
var trimmedString = flabbyString.replace(/^\s*(.*)\s*$/, '$1');
投票されたソリューションが満足のいくものではなかった。それで、私はthatsが一般的なもので、あなたのテキストの最初と最後の部分の両方で機能するものを書きました(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;
}