2017-02-08 64 views
0

我有一個函數,它根據搜索子字符串用< span>標籤包裝給定字符串的部分。用<span>標籤(與嵌套)包裝子字符串

例如爲:

「隨後趕來的第一個流星的夜晚。」

將返回(和它的確定):

「然後來到</SPAN>的< SPAN>第一</SPAN>流星的夜晚<跨度>」。

「第一個」搜索字符串。如果我們嘗試搜索字符串「第RS」(注意「RS」包含「網絡RS噸」這已經在我們的搜索字符串存在),現在它給:

「隨後趕來的夜晚< SPAN> </SPAN>< SPAN>網絡< SPAN> RS </SPAN>牛逼</SPAN>流星」的。

但我們要看到的是第一個結果:

「隨後趕來的夜晚< SPAN> </SPAN>< SPAN>第一</SPAN>流星的」。

const markSubstring = (string, searchString) => { 
 

 
    _.forEach(searchString.split(' '), function(value){ 
 
     if(value != '') { 
 
      let regEx = new RegExp('(' + value + ')', "ig"); 
 
      string = string.replace(regEx, '<span>$1</span>'); 
 
     } 
 
    }); 
 

 
    return _.map(string.split(/(<span>.*?<\/span>)/), (item, key) => { 
 
     let val = item.split(/<span>(.*?)<\/span>/); 
 
     if (val.length == 3) { return `<span>${val[1]}</span>` } 
 
     return `${val}`; 
 
    }); 
 
}; 
 

 
console.log(markSubstring('Then came the night of the first falling star.', 'first of')); 
 
console.log('---------'); 
 
console.log(markSubstring('Then came the night of the first falling star.', 'first of rs'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

什麼是修改函數來獲得期望的結果的最佳方式?

UPDATE

給定的字符串:隨後趕來的第一個流星的夜晚。

一些搜索查詢和他們的預計業績:

來到 - >然後(就)第一流星的夜晚。

第一個來 - >然後(來)的第一個流星的夜晚。 (第一顆)流星的n(ig)ht。

第一個rs - >然後是(第一個)流星的夜晚。

first rs am - >然後c(am)e(第一顆)流星的夜晚。

所以我們除以空間搜索字符串,並試圖找到每一個給定的字符串,這些「次搜索查詢」的。

使用new RegExp('(' + value + ')', "ig");我們有一個< span>在嵌套搜索時顯示爲字符串中的文本(不僅僅是它具有的樣式)。所以我認爲最好的選擇是,當這個詞(或其部分已經突出顯示)的時候不要說出來。

回答

2

編輯

OK添加以下的邏輯來完善它。

  1. 按長度對所有搜索詞進行排序,以便首先搜索最長的詞。這樣,如果搜索到較短的單詞,但已被包含爲較長單詞的一部分(已用<span>包裝),則我們不知道插入另一個跨度。
  2. 我們從字符串分割每個單詞,並確保它尚未包裹着<span>

您可以通過確保每個字是一個完整的字,而不是另一部分修復字。

例如,如果我們使用正則表達式模式:/(^|\s)(first)(\s|$)/gi 我們確保這個詞first必須跟一個空格,開頭或字符串的結尾。因此在這種情況下單詞rs不能被認爲是一個單詞。

看到它在行動:

const markSubstring = (string, searchString) => { 
 
    var searchStrings = searchString.split(' ').sort(function(a, b){return b.length - a.length;}); 
 
    
 
    _.forEach(searchStrings, function(value){ 
 
     if(value != '') { 
 
      let regEx = new RegExp('(' + value + ')', "ig"); 
 
      let validationRegEx = new RegExp('<span>.*?(' + value + ').*?<\/span>', "ig"); 
 
      var words = []; 
 
      _.forEach(string.split(' '), function(word) { 
 
       if (!word.match(validationRegEx)) { 
 
       word = word.replace(regEx, '<span>$1</span>'); 
 
       } 
 
       words.push(word); 
 
      })   
 
      string = words.join(' '); 
 
     } 
 
    }); 
 

 
    return _.map(string.split(/(<span>.*?<\/span>)/), (item, key) => { 
 
     let val = item.split(/<span>(.*?)<\/span>/); 
 
     if (val.length == 3) { return `<span>${val[1]}</span>` } 
 
     return `${val}`; 
 
    }); 
 
}; 
 

 
console.log(markSubstring('Then came the night of the first falling star.', 'first of')); 
 
console.log('---------'); 
 
console.log(markSubstring('Then came the night of the first falling star.', 'first of rs')); 
 
console.log('---------'); 
 
console.log(markSubstring('Then came the night of the first falling star. rs is also a word.', 'first of rs'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

+0

想出了基本一致的解決方案,但它沒有工作,直到我發現我完全忘了將雙反斜線事情 – Benjamin

+0

感謝快速回復!好吧,它解決了嵌套問題,但現在它只適用於整個單詞(最後有空格,沒有逗號或點)。我不擅長正則表達式。我們怎樣才能將這兩種行爲結合起來,例如在同一個字符串中的「bla bla bla bla bla」和「first rs」(正確的方式)中找到「rs」? – Max

+0

所以你想突出顯示字符串的一部分,如果該字還沒有用span來包裝? –