3

私はjavascript文字列メソッドと正規表現に苦労してきましたが、明らかな何かを見落としている可能性があります。tofutimの質問をもう少し詳しく言い換えて、プロトコルに違反しないことを願っています。彼の質問への回答はs.replace()に焦点を当てていますが、それが機能するには、置換する部分文字列の出現箇所を知るか、それらすべてを置換するか、または置換する文字列を何らかの方法で一意に識別できる必要があります。正規表現。彼のように、私は次のようなテキストオフセットの配列しか持っていません:

[[5,9], [23,27]]

そしてこのような文字列:

"eggs eggs spam and ham spam"

これらの制約を考えると、このような文字列に到達するための簡単な方法(javaScriptまたはjQueryを使用したショートカット)はありますか?

"eggs <span>eggs</span> spam and ham <span>spam</span>"

置換文字列が何であるか、またはベーステキストにそれらがいくつ出現する可能性があるかを事前に知りません。私はそれらのオフセットしか知りません、そして私がタグでラップしたいのはそれらのオフセットによって識別されたオカレンスだけです。

何かご意見は?

4

5 に答える 5

4

正規表現でそれを行う方法を見つけました。パフォーマンスについてはよくわかりませんが、短くて甘いです。

/**
 * replaceOffset
 * @param str A string
 * @param offs Array of offsets in ascending order [[2,4],[6,8]]
 * @param tag HTML tag
 */
function replaceOffset(str, offs, tag) {
  tag = tag || 'span';
  offs.reverse().forEach(function(v) {
    str = str.replace(
      new RegExp('(.{'+v[0]+'})(.{'+(v[1]-v[0])+'})'), 
      '$1<'+tag+'>$2</'+tag+'>'
    );
  });
  return str;
}

デモ: http: //jsbin.com/aqowum/3/edit

于 2012-09-20T23:26:16.637 に答える
1

メソッドを試すことができますslice

var arr = [[5,9], [23,27]];
arr = arr.reverse()

$.each(arr, function(i, v){
    var f = v[0], last = v[1];
    $('p').html(function(i, v){
        var o = v.slice(0, f);
        var a = '<span>' + v.slice(f, last) + '</span>';
        var c = v.slice(last, -1);
        return o+a+c
    })
})

http://jsfiddle.net/rjQt7/

于 2012-09-20T22:38:53.117 に答える
1

iquickソリューション(テストされていません)

function indexWrap(indexArr,str){
  // explode into array of each character
  var chars = str.split('');
  // loop through the MD array of indexes
  for(var i=0; i<indexArr.length;i++){
    var indexes = indexArr[i];
    // if the two indexes exist in the character array
    if(chars[indexes[0]] && chars[indexes[1]]){
      // add the tag into each index
      chars.splice(indexes[0],0,"<span>");
      chars.splice(indexes[1],0,"</span>");
    }
  }
  // return the joined string
  return chars.join('');  
}

個人的には、文字列置換ソリューションが好きですが、必要ない場合は、これでうまくいく可能性があります

于 2012-09-20T22:41:10.193 に答える
1

まず、以前に行った置換を最終的に上書きしないようにするために、逆方向に反復する必要がありますが、私の例では、文字列が最後に一度に再構築されるため、重要ではありません。

// > interpolateOnIndices([[5,9], [23,27]], "eggs eggs spam and ham spam");
// < 'eggs <span>eggs</span> spam and ham <span>spam</span>'

function interpolateOnIndices(indices, string) {
    "use strict";
    var i, pair, position = string.length,
        len = indices.length - 1, buffer = [];
    for (i = len; i >= 0; i -= 1) {
        pair = indices[i];
        buffer.unshift("<span>",
                       string.substring(pair[0], pair[1]),
                       "</span>",
                       string.substring(pair[1], position));
        position = pair[0];
    }
    buffer.unshift(string.substr(0, position));
    return buffer.join("");
}

spliceこれは、追加の配列を作成しないため、ingを使用した例よりも少し優れています(スプライス自体が追加の配列を作成します)。マッピングを使用して関数を他の関数内で繰り返し作成することは、特定のメモリを大量に消費しますが、あまり高速ではありません...ただし、少し短くなります。

大きな文字列では、理論的には、結合すると、複数の連結よりも有利になります。これは、メモリの割り当てが、後で中途半端な文字列を破棄するのではなく、一度だけ行われるためです。もちろん、大量のデータを処理しているのでない限り、これらすべてを気にする必要はありません。


編集:

手に余る時間があったので、テストを行うことにしました。より大きな(しかしかなり現実的な)データセットでバリエーションがどのように比較されるかを確認するために、以下にいくつかの結果を含むテストコードを示します...

function interpolateOnIndices(indices, string) {
    "use strict";
    var i, pair, position = string.length,
        len = indices.length - 1, buffer = [];
    for (i = len; i >= 0; i -= 1) {
        pair = indices[i];
        buffer.unshift("<span>",
                       string.substring(pair[0], pair[1]),
                       "</span>",
                       string.substring(pair[1], position));
        position = pair[0];
    }
    buffer.unshift(string.substr(0, position));
    return buffer.join("");
}

function indexWrap(indexArr, str) {
    var chars = str.split("");
    for(var i = 0; i < indexArr.length; i++) {
        var indexes = indexArr[i];
        if(chars[indexes[0]] && chars[indexes[1]]){
            chars.splice(indexes[0], 0, "<span>");
            chars.splice(indexes[1], 0, "</span>");
        }
    }
    return chars.join("");
}

function replaceOffset(str, offs, tag) {
    tag = tag || "span";
    offs.reverse().forEach(
        function(v) {
            str = str.replace(
                new RegExp("(.{" + v[0] + "})(.{" + (v[1] - v[0]) + "})"), 
                "$1<" + tag + ">$2</" + tag + ">"
            );
        });
    return str;
}

function generateLongString(pattern, times) {
    "use strict";
    var buffer = new Array(times);
    while (times >= 0) {
        buffer[times] = pattern;
        times -= 1;
    }
    return buffer.join("");
}

function generateIndices(pattern, times, step) {
    "use strict";
    var buffer = pattern.concat(), block = pattern.concat();
    while (times >= 0) {
        block = block.concat();
        block[0] += step;
        block[1] += step;
        buffer = buffer.concat(block);
        times -= 1;
    }
    return buffer;
}

var longString = generateLongString("eggs eggs spam and ham spam", 100);
var indices = generateIndices([[5,9], [23,27]], 100,
                              "eggs eggs spam and ham spam".length);

function speedTest(thunk, times) {
    "use strict";
    var start = new Date();
    while (times >= 0) {
        thunk();
        times -= 1;
    }
    return new Date() - start;
}

speedTest(
    function() {
        replaceOffset(longString, indices, "span"); },
    100); // 1926

speedTest(
    function() {
        indexWrap(indices, longString); },
    100); // 559

speedTest(
    function() {
        interpolateOnIndices(indices, longString); },
    100); // 16

amd64 Linux(FC-17)でV8(Node.js)に対してテストされています。

そのライブラリをロードしたくなかったので、undefinedの答えをテストしませんでした。特に、このテストに役立つことは何もしません。私はそれがandbeyondとelclanrsの変種の間のどこかで、しかしelclanrsの答えにもっと役立つだろうと想像します。

于 2012-09-20T23:18:39.553 に答える
0

サブストリングメソッドString.substring(startIndex、endIndex);を使用できます。説明:開始インデックスと終了インデックスの使用の間の文字列を返します:

var source="hello world";
var result=source.substring (3,7); //returns 'lo wo'

最初と最後のインデックスを持つ配列がすでにあるので、ほぼ完了です:)

于 2012-09-20T22:39:59.680 に答える