搜尋

首頁  >  問答  >  主體

如何讓這個正規表示式簡化?

我有這個正規表示式:

"(WORD1.*WORD2.*WORD3)|(WORD1.*WORD3.*WORD2)|(WORD2.*WORD1.*WORD3)|(WORD2.*WORD3.*WORD1)|(WORD3.*WORD1. *WORD2)|(WORD3.*WORD2.*WORD1)"

它與這些單字相符:

WORD1WORD2WORD3
WORD1AWORD2BWORD3C
WORD3WORD1WORD2
WORD1WORD2WORD3WORD1

但不是這些話:

WORD1WORD1WORD2
WORD1AWORD1BWORD2C

當該正規表示式找到包含任意順序的3 個單字(WORD1WORD2WORD3)的字串時,它就會匹配。

我想用更多的單字做同樣的事情,但問題是正規表示式的大小隨著單字的數量呈指數增長。 是否可以簡化此正規表示式的構造方式來解決此問題(大小不會呈指數增長)?

P粉710454910P粉710454910348 天前442

全部回覆(2)我來回復

  • P粉663883862

    P粉6638838622024-02-27 16:51:16

    簡單地迭代所有字串並過濾掉所有不包含所有關鍵字的字串:

    (可以在下面的程式碼片段中找到更簡潔的版本)

    function findMatch(strings, keywords) {
      const result = [];
      
      for (const string of strings) {
        if (keywords.every(keyword => string.includes(keyword))) {
          result.push(string);
        }
      }
      
      return result;
    }
    

    嘗試一下:

    console.config({ maximize: true });
    
    function findMatch(strings, keywords) {
      return strings.filter(
        string => keywords.every(keyword => string.includes(keyword))
      );
    }
    
    const testcases = [
      'WORD1WORD2WORD3',
      'WORD1AWORD2BWORD3C',
      'WORD3WORD1WORD2',
      'WORD1WORD2WORD3WORD1',
      'WORD1WORD1WORD2',
      'WORD1AWORD1BWORD2C'
    ];
    
    const keywords = [
      'WORD1', 'WORD2', 'WORD3'
    ];
    
    console.log(findMatch(testcases, keywords));

    回覆
    0
  • P粉998100648

    P粉9981006482024-02-27 11:50:29

    您可以對每個單字使用正向前瞻。

    /(?=.*WORD1)(?=.*WORD2)(?=.*WORD3).*/

    下面的更高效能版本指定起始錨點,並且在驗證前瞻後僅符合單一字元。根據OP的要求,此技術僅適用於matching,而不適用於extraction

    /^(?=.*WORD1)(?=.*WORD2)(?=.*WORD3)./

    正向先行就像一個門,只有當括號內指定的匹配存在時,它才會繼續,但它不會消耗或捕獲它匹配的內容——它總是零長度。如果您「向前看」以查看每個單字前面是否存在 .*,那麼這些單字的順序並不重要。如果每個單字為真,則繼續進行,而不會使用任何內容進行配對。

    如果您只關心內容是否匹配,那麼兩個表達式之間唯一的實質差異就是它們花費的時間。假設您的內容中只有 3 個必需單字中的 2 個。除非解釋表達式的軟體能夠識別嘗試是徒勞的,否則它可能會在第一個位置查找三個單字“失敗”,然後在第二個位置嘗試“失敗”,等等,直到到達最後一個位置才放棄。透過指定^,只會在第一個位置進行檢查,節省了其他不必要檢查的時間。當您只是尋找內容中是否存在所有單字的真/假答案時,從末尾刪除 * 可以防止一些不必要的捕獲。

    回覆
    0
  • 取消回覆