長い文字列を切り捨てるスマートな方法


187

JavaScriptを使用して文字列を切り捨て、最後に省略記号を付けるためのより洗練されたソリューション/ライブラリを持っている人はいますか?

if (string.length > 25) {
  string = string.substring(0, 24) + "...";
}

5
「より洗練された」とはどういう意味ですか?単語の境界を考慮に入れる関数?
Residuum 2009

2
また、HTMLタグの途中で切り捨てられません。
Sz。

回答:


366

基本的に、与えられた文字列の長さをチェックします。指定された長さより長い場合は、n長さnsubstrまたはslice)に切り取り、htmlエンティティ…(…)を切り取った文字列に追加します。

そのような方法は次のようになります

function truncate(str, n){
  return (str.length > n) ? str.substr(0, n-1) + '…' : str;
};

「より洗練された」とは、文字列の最後の単語の境界で切り捨てることを意味する場合は、追加のチェックが必要です。最初に文字列を目的の長さにクリップし、次にその結果を最後の単語の境界にクリップします

function truncate( str, n, useWordBoundary ){
  if (str.length <= n) { return str; }
  const subString = str.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

String関数を使用してネイティブプロトタイプを拡張できます。その場合、strパラメーターを削除strし、関数内をthis次のように置き換える必要があります。

String.prototype.truncate = String.prototype.truncate || 
function ( n, useWordBoundary ){
  if (this.length <= n) { return this; }
  const subString = this.substr(0, n-1); // the original check
  return (useWordBoundary 
    ? subString.substr(0, subString.lastIndexOf(" ")) 
    : subString) + "&hellip;";
};

もっと独断的な開発者があなたを強く捕らえるかもしれません(「あなたが所有していないオブジェクトを変更しないでください」。私は気にしません)。

Stringプロトタイプを拡張しないアプローチは、提供する(長い)文字列とそれを切り捨てる前述のメソッドを含む独自のヘルパーオブジェクトを作成することです。それが以下のスニペットです。

最後に、CSSを使用できるのは、HTMLノードの長い文字列を切り捨てる場合のみです。それはあなたにあまり制御を与えませんが、実行可能な解決策であるかもしれません。


5
たとえば、文字列が500文字より長い場合など、「ハード」と「ソフト」の制限も考慮する必要があります。これは、ユーザーがテキスト全体を表示したい場合にリンクをクリックすると便利な場合があります。それのための。その結果、1文字または2文字をさらにロードすると、見苦しくなります。
Maxim Sloyko、2009

2
の2番目のパラメーターsubstrは長さなので、substr(0,n)代わりに最初のn文字に制限する必要があります。
JohnnyHK 2013

10
所有していないオブジェクトは変更しないでください。nczonline.net/blog/2010/03/02/…–
チャーリーキリアン

5
コード例で、&hellip;を実際の省略記号(...)に置き換えることを検討してください。APIを操作するためにこれを使用しようとしている場合は、そこに非HTMLエンティティが必要です。
AlbertEngelB 14

1
@RuneJeppesenあなたは正しい。メソッドを調整しました。私の弁護へ:答えは7年前にさかのぼります;)
KooiInc '15

62

これはFirefoxでのみ実行する必要があることに注意してください。

他のすべてブラウザーはCSSソリューションをサポートしていますサポート表を参照):

p {
    white-space: nowrap;
    width: 100%;                   /* IE6 needs any width */
    overflow: hidden;              /* "overflow" value must be different from  visible"*/ 
    -o-text-overflow: ellipsis;    /* Opera < 11*/
    text-overflow:    ellipsis;    /* IE, Safari (WebKit), Opera >= 11, FF > 6 */
}

皮肉なことに、私はそのコードスニペットをMozilla MDCから取得しました。


1
mattsnider.com/css/css-string-truncation-with-ellipsisを使用して、FFでも動作するようにします。
Neal

これはモバイルSafariに最適なソリューションです。ありがとうございました!
samvermette

9
非常に優れたCSSアプローチ。これは1行のテキストでのみ機能することに注意してくださいwhite-space: nowrap;。複数行になると、JavaScriptに悩まされます。
insertusernamehere 2012

また、要素全体に対してのみ機能します。文字列の一部を切り捨てる場合、切り捨てたいビットをスパンまたは他のhtml要素でラップしないと、これは機能しません。例:Your picture ('some very long picture filename truncated...') has been uploaded.
Chris

1
OPは特にjavascriptソリューションを求めていました
vsync

24

CSSではなくJavaScriptでこれを実行することを望む正当な理由があります。

JavaScriptで8文字(省略記号を含む)に切り捨てるには:

short = long.replace(/(.{7})..+/, "$1&hellip;");

または

short = long.replace(/(.{7})..+/, "$1…");

省略記号を数えると、これは9文字になります。切り捨て後に8にする必要がある場合は、.replace(/^(.{7}).{2,}/, "$1…");代わりに使用してください
Okku

longそしてshort、古いECMAScript仕様(ECMAScript 1から3)によって将来のキーワードとして予約されています。MDN:古い標準の将来の予約キーワードを
Ricardo


9
('long text to be truncated').replace(/(.{250})..+/, "$1…");

どういうわけか、上記のコードは、vuejsアプリでコピーまたは貼り付けられたテキストの種類に対して機能しませんでした。そこで、lodash truncateを使用しましたが、現在は正常に機能しています。

_.truncate('long text to be truncated', { 'length': 250, 'separator': ' '});

素敵なモダンな答え!
ykonda

テキストが何であるか知りたいです。非ラテン文字を使用していましたか?
Adam Leggett

それは単なるlorem ipsum
でした

7

これが他の提案よりもいくつかの改善点がある私の解決策です:

String.prototype.truncate = function(){
    var re = this.match(/^.{0,25}[\S]*/);
    var l = re[0].length;
    var re = re[0].replace(/\s$/,'');
    if(l < this.length)
        re = re + "&hellip;";
    return re;
}

// "This is a short string".truncate();
"This is a short string"

// "Thisstringismuchlongerthan25characters".truncate();
"Thisstringismuchlongerthan25characters"

// "This string is much longer than 25 characters and has spaces".truncate();
"This string is much longer&hellip;"

それ:

  • 25文字の後の最初のスペースで切り捨てます
  • JavaScriptのStringオブジェクトを拡張して、任意の文字列で使用(および連鎖)できるようにします。
  • 切り捨てによって末尾のスペースが生じる場合は、文字列をトリムします。
  • 切り詰められた文字列が25文字より長い場合、Unicodeのhellipエンティティ(省略記号)を追加します

7

私が見つけた最高の機能。text-ellipsisへのクレジット。

function textEllipsis(str, maxLength, { side = "end", ellipsis = "..." } = {}) {
  if (str.length > maxLength) {
    switch (side) {
      case "start":
        return ellipsis + str.slice(-(maxLength - ellipsis.length));
      case "end":
      default:
        return str.slice(0, maxLength - ellipsis.length) + ellipsis;
    }
  }
  return str;
}

var short = textEllipsis('a very long text', 10);
console.log(short);
// "a very ..."

var short = textEllipsis('a very long text', 10, { side: 'start' });
console.log(short);
// "...ng text"

var short = textEllipsis('a very long text', 10, { textEllipsis: ' END' });
console.log(short);
// "a very END"

5

現在のすべてのブラウザーは、テキスト行が使用可能な幅を超えた場合に省略記号を自動的に追加するためのシンプルなCSSソリューションをサポートしています。

p {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

(これを有効にするには、要素の幅を何らかの方法で制限する必要があることに注意してください。)

https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/に基づいています

このアプローチはないことに留意すべきでない文字の数に基づいて制限します。複数行のテキストを許可する必要がある場合にも機能しませ


2
これは単一行の文にのみ役立ちます。CSSを使用して複数行の例を実行する方法はありません(私の知る限り)。
Hooman Askari 2016

これを右ではなく左の省略記号にする方法はありますか?
GreenAsJade

1
私はあなたが使用していることを達成することができると信じてい@GreenAsJade text-direction: rtltext-align: leftdavidwalsh.name/css-ellipsis-left
Sean the Beanを

4

最近のほとんどのJavaScriptフレームワーク(jQueryのプロトタイプなどが ...)そのハンドルこの文字列を上タックユーティリティ機能を持っています。

これがプロトタイプの例です:

'Some random text'.truncate(10);
// -> 'Some ra...'

これは、誰かに処理/維持してほしい機能の1つに思えます。もっとコードを書くのではなく、フレームワークに処理を任せます。


8
jQueryにはこれについては何もないと思います。
アレックス、

2
Underscore.jsは-_( 'Hello world')。truncate(5)=> 'Hello ...' _( 'Hello')。truncate(10)=> 'Hello'
JayCrossler

3
Pure Underscoreにもないようです-underscore.string truncate()などの拡張機能が必要になる場合があります
2014年

2
これは完全に正しい答えです。アンダースコアについては知りませんが、lodashは_.truncこれを正確に実行します。
leftclickben 2015年

2
私は正しい答えはlodash.truncまたはunderscore.string.truncateを使用することだと思います。
ooolala

2

多分誰かがnullを処理している例を見逃したかもしれませんが、nullがあったときに3つのTOP回答が私にとってうまくいきませんでした既存の関数と、他の人に提供するだろうと思った優れた省略記号の回答の1つを使用しました。

例えば

javascript:

news.comments

切り捨て関数の使用

news.comments.trunc(20, true);

ただし、news.commentsがnullの場合 、「壊れる」

最後の

checkNull(news.comments).trunc(20, true) 

KooiInc提供のtrunc関数

String.prototype.trunc =
 function (n, useWordBoundary) {
     console.log(this);
     var isTooLong = this.length > n,
         s_ = isTooLong ? this.substr(0, n - 1) : this;
     s_ = (useWordBoundary && isTooLong) ? s_.substr(0, s_.lastIndexOf(' ')) : s_;
     return isTooLong ? s_ + '&hellip;' : s_;
 };

私の単純なnullチェッカー(リテラルの "null"もチェックします(これは、未定義、 ""、null、 "null"などをキャッチします)。

  function checkNull(val) {
      if (val) {
          if (val === "null") {
              return "";
          } else {
              return val;
          }
      } else {
          return "";
      }
  }

これは変更されたバージョンです-プロトタイプの使用を避け、関数にnullチェックを組み込んでおり、テスト/デモの使用法があります。codepen.io/mahemoff/pen/LGEdzy
mahemoff

プロトタイプに問題があると思いますか?好奇心旺盛
トムスティッケル

私の別のヌルチェック機能の理由未定義、それが実際にnullをチェックすることで、NaNの場合、空の文字列(「」)、0、偽および「ヌル」しかし、あなたのFXのような全体的なI
トムStickel

1
うん、それは意見と使用状況の問題ですが、プロトタイプは他のライブラリを使用しているときに同じものをオーバーライドする可能性があるため、醜くなります。(またはまれに、同じ名前の関数が後で標準言語機能として導入される場合があります。)
mahemoff

はい、同意します
Tom Stickel

2

ファイル名には番号が付けられている場合があり、インデックスが最初または最後にある場合があります。だから私は文字列の中心から短くしたかった:

function stringTruncateFromCenter(str, maxLength) {
    const midChar = "…";      // character to insert into the center of the result
    var left, right;

    if (str.length <= maxLength) return str;

    // length of beginning part      
    left = Math.ceil(maxLength / 2);

    // start index of ending part   
    right = str.length - Math.floor(maxLength / 2) + 1;   

    return str.substr(0, left) + midChar + str.substring(right);
}

ここでは、UTF-8で1バイトを超えるフィル文字を使用したことに注意してください。



1

Kooilncのソリューションに賛成しました。本当に素晴らしいコンパクトなソリューション。対処したい小さなケースが1つあります。誰かが何らかの理由で非常に長い文字シーケンスを入力しても、切り詰められません。

function truncate(str, n, useWordBoundary) {
    var singular, tooLong = str.length > n;
    useWordBoundary = useWordBoundary || true;

    // Edge case where someone enters a ridiculously long string.
    str = tooLong ? str.substr(0, n-1) : str;

    singular = (str.search(/\s/) === -1) ? true : false;
    if(!singular) {
      str = useWordBoundary && tooLong ? str.substr(0, str.lastIndexOf(' ')) : str;
    }

    return  tooLong ? str + '&hellip;' : str;
}

1

すばやくグーグルでこれを見つけまし ...それはあなたのために機能しますか?

/**
 * Truncate a string to the given length, breaking at word boundaries and adding an elipsis
 * @param string str String to be truncated
 * @param integer limit Max length of the string
 * @return string
 */
var truncate = function (str, limit) {
    var bits, i;
    if (STR !== typeof str) {
        return '';
    }
    bits = str.split('');
    if (bits.length > limit) {
        for (i = bits.length - 1; i > -1; --i) {
            if (i > limit) {
                bits.length = i;
            }
            else if (' ' === bits[i]) {
                bits.length = i;
                break;
            }
        }
        bits.push('...');
    }
    return bits.join('');
};
// END: truncate

1

テキストのオーバーフロー:省略記号は必要なプロパティです。これと特定の幅のoverflow:hiddenを使用すると、最後に3つのピリオド効果が得られるすべてを超えます... whitespace:nowrapを追加することを忘れないでください。そうしないと、テキストが複数行に配置されます。

.wrap{
  text-overflow: ellipsis
  white-space: nowrap;
  overflow: hidden;
  width:"your desired width";
}
<p class="wrap">The string to be cut</p>

1
簡潔さは許容されますが、完全な説明の方が優れています。
アルマリ

mwilcoxSean the Beanはすでにこのソリューションを投稿しています。
アンドリューマイヤーズ

1
1行のテキストにのみ使用できます
Vally Pepyako

テキストのオーバーフロー:省略は完璧です!!
zardilior

0

c_harmの答えは私の意見では最高です。使用したい場合はご注意ください

"My string".truncate(n)

リテラルではなく、正規表現オブジェクトコンストラクタを使用する必要があります。また\S、変換時にをエスケープする必要があります。

String.prototype.truncate =
    function(n){
        var p  = new RegExp("^.{0," + n + "}[\\S]*", 'g');
        var re = this.match(p);
        var l  = re[0].length;
        var re = re[0].replace(/\s$/,'');

        if (l < this.length) return re + '&hellip;';
    };

コメントや適切な変数の命名について聞いたことはありますか?
自転車

@bicycleコードは上記の別の回答からコピーされ変更されています。
Matt Fletcher

0

次のコードを使用

 function trancateTitle (title) {
    var length = 10;
    if (title.length > length) {
       title = title.substring(0, length)+'...';
    }
    return title;
}

0

Kooilncのソリューションの修正:

String.prototype.trunc = String.prototype.trunc ||
  function(n){
      return this.length>n ? this.substr(0,n-1)+'&hellip;' : this.toString();
  };

これは、切り捨てる必要がない場合、Stringオブジェクトの代わりに文字列値を返します。


これは質問に対する答えを提供しません。批評したり、著者に説明を要求したりするには、投稿の下にコメントを残します。自分の投稿にはいつでもコメントできます。十分な評判得られれ、どの投稿にもコメントできます。
Spencer Wieczorek 2014年

ああ、今は違いがわかります。参照をありがとう。私は@Kooilncがそれを見てくれることを期待してコメントを残したいと思いました。彼または彼女が同意したが、評判がなかった場合は、受け入れられた回答を編集する可能性があります。
qwales1 2014年

0

私は最近これをしなければならず、次のようになりました:

/**
 * Truncate a string over a given length and add ellipsis if necessary
 * @param {string} str - string to be truncated
 * @param {integer} limit - max length of the string before truncating
 * @return {string} truncated string
 */
function truncate(str, limit) {
    return (str.length < limit) ? str : str.substring(0, limit).replace(/\w{3}$/gi, '...');
}

私に素敵で清潔な感じ:)


1
これにより、結果の文字列が制限より3文字長くなる可能性があります。
Hauke

0

.slice()を使うのが好きです。最初の引数は開始インデックスで、2番目の引数は終了インデックスです。その間のすべてがあなたが取り戻すものです。

var long = "hello there! Good day to ya."
// hello there! Good day to ya.

var short  = long.slice(0, 5)
// hello

0

どこかスマート:D

//My Huge Huge String
    let tooHugeToHandle = `It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).`
    
//Trim Max Length
 const maxValue = 50
// The barber.
 const TrimMyString = (string, maxLength, start = 0) => {
//Note - `start` is if I want to start after some point of the string
    	if (string.length > maxLength) {
    	let trimmedString = string.substr(start, maxLength)
    	 return (
    	   trimmedString.substr(
    	   start,
    	   Math.min(trimmedString.length,   trimmedString.lastIndexOf(' '))
           ) + ' ...'
         )
       }
    return string
}

console.log(TrimMyString(tooHugeToHandle, maxValue))


-1

この関数は、スペースと単語の一部も切り捨てます(例:母を蛾に...)

String.prototype.truc= function (length) {
        return this.length>length ? this.substring(0, length) + '&hellip;' : this;
};

使用法:

"this is long length text".trunc(10);
"1234567890".trunc(5);

出力:

これは...

12345 ...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.