2012-09-20 46 views
3

我一直在使用JavaScript字符串方法和正則表達式掙扎,並且我可能會忽略某些明顯的東西。我希望我能通過更詳細地重申tofutim的question來違反任何協議。對他的問題的迴應集中在s.replace()上,但爲了工作,您必須知道要替換的子字符串出現的位置,替換所有字符串,還是能夠唯一標識要替換的字符串正則表達式。和他一樣,我只有有文本偏移量的一個這樣的數組:只使用文本偏移量在字符串中插入標籤

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

像這樣的字符串:

"eggs eggs spam and ham spam" 

鑑於這些約束,有一個簡單的方法(JavaScript或一些捷徑與jQuery)到達這樣的字符串?

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

我不知道提前替換字符串是什麼,或者他們中的許多事件如何有可能是在基礎文本。我只知道他們的偏移量,它只是只有我們想要用標籤包裹的偏移量識別的事件。

有什麼想法?

+1

我想你需要一個分析器,而不是一個簡單的與string.replace()方法。你當然可以用string.replace()來做到這一點,但它會變得很慢。一次讀取一個字符,標記字符串,對數組進行處理並生成輸出字符串可能會更有效。 – jrista

+0

感謝@jrista,也許是這樣的:'升= s.split( '')''然後L [5] = 「」 + A [5]'同樣地,對於每個偏移對每個元素,然後加入結果?我會嘗試的。 – jjon

+0

這就是類似於我的反應居然 – anson

回答

3

我找到了一種方法用正則表達式來做到這一點。不知道性能,但它的短期和甜:

/** 
* 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

+0

這正是我整天在跳舞的解決方案。謝謝,你找到了! – jjon

+0

太棒了!我現在可以刪除140行代碼嘗試。 – PapaSierra

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/

0

你可以使用的子方法 String.substring(的startIndex,endIndex的); 描述:返回開始&結束索引之間的字符串 用法:

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

您已經有了初步&最終索引數組,所以你幾乎完成:)

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

就個人而言,我喜歡一個字符串替換解決方案,但如果你不想一個,這可能工作

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 

測試對V8(Node.js的)在AMD64的Linux(FC-17)。

我沒有測試的不確定的答案,因爲我不希望加載該庫,特別是因此它不會做任何事情,這個測試非常有用。我可以想象它會在兩者之間以及elclanrs的變體之間出現,更多的是對elclanrs的回答。

+0

在我的情況下,速度增益是不是真的相關,但這是很好的瞭解,感謝@wvxvw。 – jjon