在 JavaScript 中缩短字符串而不剪切单词
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5454235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shorten string without cutting words in JavaScript
提问by Josh Bedo
I'm not very good with string manipulation in JavaScript, and I was wondering how you would go about shortening a string without cutting any word off. I know how to use substring, but not indexOf or anything really well.
我不太擅长 JavaScript 中的字符串操作,我想知道如何在不切断任何单词的情况下缩短字符串。我知道如何使用子字符串,但不知道如何使用 indexOf 或任何非常好的东西。
Say I had the following string:
假设我有以下字符串:
text = "this is a long string I cant display"
I want to trim it down to 10 characters, but if it doesn't end with a space, finish the word. I don't want the string variable to look like this:
我想将其缩减为 10 个字符,但如果它不以空格结尾,请完成该单词。我不希望字符串变量看起来像这样:
"this is a long string I cant dis"
“这是我无法分辨的长字符串”
I want it to finish the word until a space occurs.
我希望它完成这个词,直到出现空格。
回答by NT3RP
If I understand correctly, you want to shorten a string to a certain length (e.g. shorten "The quick brown fox jumps over the lazy dog"
to, say, 6 characters without cutting off any word).
如果我理解正确,您想将字符串缩短到一定长度(例如缩短"The quick brown fox jumps over the lazy dog"
到 6 个字符而不切断任何单词)。
If this is the case, you can try something like the following:
如果是这种情况,您可以尝试以下操作:
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(" ")))
}
回答by Hamish
There are lots of ways to do it, but a regular expression is a useful one line method:
有很多方法可以做到这一点,但正则表达式是一种有用的单行方法:
"this is a longish string of text".replace(/^(.{11}[^\s]*).*/, "");
//"this is a longish"
This expressions returns the first 11 (any) characters plus any subsequent non-space characters.
此表达式返回前 11 个(任何)字符以及任何后续的非空格字符。
Example script:
示例脚本:
<pre>
<script>
var t = "this is a longish string of text";
document.write("1: " + t.replace(/^(.{1}[^\s]*).*/, "") + "\n");
document.write("2: " + t.replace(/^(.{2}[^\s]*).*/, "") + "\n");
document.write("5: " + t.replace(/^(.{5}[^\s]*).*/, "") + "\n");
document.write("11: " + t.replace(/^(.{11}[^\s]*).*/, "") + "\n");
document.write("20: " + t.replace(/^(.{20}[^\s]*).*/, "") + "\n");
document.write("100: " + t.replace(/^(.{100}[^\s]*).*/, "") + "\n");
</script>
Output:
输出:
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
回答by Chris Cinelli
I am kind of surprised that for a simple problem like this there are so many answers that are difficult to read and some, including the chosen one, do not work .
我有点惊讶,对于这样一个简单的问题,有这么多难以阅读的答案,有些答案,包括所选的答案,都不起作用。
I usually want the result string to be at mostmaxLen
characters.
I also use this same function to shorten the slugs in URLs.
我通常希望结果字符串最多为maxLen
字符。我也使用相同的函数来缩短 URL 中的 slug。
str.lastIndexOf(searchValue[, fromIndex])
takes a second parameter that is the index at which to start searching backwards in the string making things efficient and simple.
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));
}
This is a sample output:
这是一个示例输出:
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"
And for the slug:
对于蛞蝓:
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"
回答by kennebec
Everyone seems to forget that indexOf takes two arguments- the string to match, and the character index to start looking from. You can break the string at the first space after 10 characters.
每个人似乎都忘记了 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
*/
回答by Leon Li
Lodash has a function specifically written for this: _.truncate
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...'
回答by Sebastien Lorber
Based on NT3RP answer which does not handle some corner cases, I've made this code.
It guarantees to not return a text with a size > maxLength event an ellipsis ...
was added at the end.
基于不处理某些极端情况的 NT3RP 答案,我制作了这段代码。它保证不返回带有 size > maxLength 事件的文本,...
最后添加了省略号。
This also handle some corner cases like a text which have a single word being > 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;
}
I guess you can easily remove the jquery dependency if this bothers you.
如果这让您感到困扰,我想您可以轻松删除 jquery 依赖项。
回答by Joakim Poromaa Helger
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));
回答by Michael Giovanni Pumo
I'm late to the party, but here's a small and easy solution I came up with to return an amount of words.
我迟到了,但这是我想出的一个小而简单的解决方案来返回大量单词。
It's not directly related to your requirement of characters, but it serves the same outcomethat I believe you were after.
它与您对characters的要求没有直接关系,但它提供的结果与我相信您所追求的结果相同。
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, '...'));
See the working example here: https://jsfiddle.net/bx7rojgL/
请参阅此处的工作示例:https: //jsfiddle.net/bx7rojgL/
回答by Pete
I took a different approach. While I needed a similar result I wanted to keep my return value less than the specified length.
我采取了不同的方法。虽然我需要类似的结果,但我想让我的返回值小于指定的长度。
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 || '');
}
EditI refactored it a bit here: JSFiddle Example. It rejoins the original array instead of concatenating.
编辑我在这里重构了一下: 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 || '');
}
回答by Roko C. Buljan
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"