2017-08-29 76 views
1

我想重現嵌套Regex_MATCH函數在Google表格上,但使用匹配表(以便我可以更容易地適應/編輯)。它應該與數組一起工作,因爲我將它與arrayformula一起使用。谷歌表格腳本連續/嵌套正則表達式

Test sheet link

例如:我想更換一個像這樣的公式:

=arrayformula(if(len(A2:A)>1,If(REGEXMATCH(A2:A, "[bB]lue[bB]alloon|Blue_Balloon"),"BlueBalloon_2017", 
IF(REGEXMATCH(A2:A, "[hH]ydraphase"),"Hydraphase_2017", 
IF(REGEXMATCH(A2:A, "[sS]kinchecker"),"Skinchecker_2017"))),"")) 

通過簡單:

=arrayformula(if(len(A2:A)>1,regexTable(A2:A),"") 

凡regexTable是一個自定義功能

// function loop RE_table named range and get matching value in result_table 
function regexTable() 
{ 
    var s = SpreadsheetApp.getActiveSpreadsheet(); 
    var refs = s.getSheetByName('refs') //get range in refs worksheet 
    var RE_table = refs.getRange("D2:D4").getvalues; // list of regular expressions to test 
    var result_table = refs.getRange("E2:E4").getvalues; // results to return if REGEX_MATCH = TRUE 

    var numRows = RE_table.getNumRows(); // loop through all regular expressions to test 
    for (var i = 1; i <= numRows; i++) { // I would like to exist loop as soon as REGEX_MATCH = TRUE 
    if(RE_table[i][1].test()) 
    return result_table[i][1]   
    } 
} 

這是我第一次搞亂谷歌腳本編輯器,所以我的問題是:

  1. 什麼不起作用?
  2. 這怎麼可能運行儘可能快?

非常感謝, 來自瑞士的歡呼聲。

+0

爲什麼不使用像'= ARRAYFORMULA(PROPER(REGEXREPLACE(A1:A, 「([AZ] | [AZ])(\ w +)」, 「$ 1 $ 2_2017」)))' –

+0

,因爲正則表達式和期望的結果字符串的輸入可能會與此公式返回的值不同 – user7736602

回答

0

使用

由於從表單自定義函數:

=getRegexTable(matchArray, regexs, replaces)

功能

粘貼到腳本編輯器:

/** 
    * returnType - "row" or "column" (default) 
*/ 
function getRegexTable(matchArray, regexs, replaces, returnType) { 
    // convert attays to lines 
    matchArray = convertArrayIntoLine(matchArray); 
    matchArray = convertArrayIntoLine(matchArray); 
    matchArray = convertArrayIntoLine(matchArray); 

    returnType = returnType || "column" // set dafault to rows 
    var machValue = ''; 
    var result = []; 
    // for each machValue 
    for (var i = 0, ii = matchArray.length; i < ii; i++) 
    { 
    machValue = matchArray[i]; 
    result.push(getRegexList(machValue, regexs, replaces));  
    } 
    if (returnType == "column") return convertLineIntoColumn(result); 
    return result; 
} 

function getRegexList(machValue, regexs, replaces, defaultResult) 
{ 
    var defaultResult = defaultResult || ''; 
    var regex; 
    // for each regex 
    for (var i = 0, ii = regexs.length; i < ii; i++) 
    { 
    if(machValue.match(new RegExp(regexs[i]))) return replaces[i];  
    } 
    return defaultResult; 
} 

function convertArrayIntoLine(array) 
{ 
    if (!Array.isArray(array[0])) return array; 
    var row = []; 
    var result = []; 
    for (i = 0, ii = array.length; i < ii; i++) 
    { 
    row = array[i]; 
    for (var j = 0, jj = row.length; j < jj; j++) 
    { 
     result.push(row[j]); 
    } 
    } 
    return result; 
} 

function convertLineIntoColumn(array) 
{ 
    var result = []; 
    for (var i = 0, ii = array.length; i < ii; i++) 
    { 
    result.push([array[i]]); 
    } 
    return result 
} 

測試

我使用此代碼測試它:

function test_getRegexTable() 
    { 
     var matchArray = [ 
     'Hydraphase boo', 
     'bar Skinchecker', 
     'BlueBalloon foo', 
     'BlueBalloon foo', 
     'bar Skinchecker', 
     'boo']; 

     var regexs = [ 
     '[bB]lue[bB]alloon|Blue_Balloon', 
     '[hH]ydraphase', 
     '[sS]kinchecker']; 

     var replaces = [ 
      'BlueBalloon_2017', 
      'Hydraphase_2017', 
      'Skinchecker_2017'] 

     Logger.log(getRegexTable(matchArray, regexs, replaces)); 
     /* result: 
     [ 
     [Hydraphase_2017], 
     [Skinchecker_2017], 
     [BlueBalloon_2017], 
     [BlueBalloon_2017], 
     [Skinchecker_2017], 
     []] 
     */ 
    } 


    function test_convertArrayIntoLine() 
    { 
     var array = [1, 2, 3]; 
     Logger.log(convertArrayIntoLine(array)); 
     array = [[1,2], [3,4]]; 
     Logger.log(convertArrayIntoLine(array)); 
    } 

    function test_convertLineIntoColumn() 
    { 
     var array = [1, 2, 3]; 
     Logger.log(convertLineIntoColumn(array)); 
    } 
+0

這麼酷,但像往常一樣的幾個問題。爲什麼三重matchArray = convertArrayIntoLine(matchArray)? +在getRegexList中,如果匹配正確,if循環不會中斷?可以這樣做,以便它始終返回第一個匹配+運行時間更快? – user7736602

+0

+在我看來,你正在將列數組轉換爲一行,然後將其轉換回列數組,唯一的目的是該函數可能適用於水平和垂直數組的權利? – user7736602

+0

正確的,唯一的目的是功能潛在的水平和垂直陣列的權利。 +使用數組作爲線更容易。 –

0

你可以使用這個公式,請嘗試:

=ArrayFormula( VLOOKUP(TRANSPOSE(REGEXREPLACE(QUERY(--REGEXMATCH(TRANSPOSE(D2:D8),OFFSET(A2,,,COUNTA(A2:A)))* ROW(OFFSET(A2,,,COUNTA(A2:A))),,COUNTA(A2:A)),"0 | 0","")*1),{ROW(B:B),B:B},2,))

範圍A2:B包含所有的正則表達式和替換字符串:

[bB]lue[bB]alloon|Blue_Balloon  BlueBalloon_2017 
[hH]ydraphase      Hydraphase_2017 
[sS]kinchecker      Skinchecker_2017 

細胞D2:D4包含文本: enter image description here


說明

Dasic想法:vlookup row_indexes: =ArrayFormula(VLOOKUP(row_indexes,{ROW(B:B),B:B},2,))

所以,問題是要找到row_indexes。

  1. 得到matching_results:REGEXMATCH(TRANSPOSE(D2:D8),OFFSET(A2,,,COUNTA(A2:A)))* ROW(OFFSET(A2,,,COUNTA(A2:A)))使用traspose這裏,因爲匹配的結果是二維數組。
  2. 擺脫額外matching_results的:REGEXREPLACE(QUERY(matching_results,,COUNTA(A2:A)),"0 | 0","")*1
  3. 使用第二tranpose到指標再次轉化成一行:... ... VLOOKUP(TRANSPOSE

如果一些字符串匹配從更多然後1點的正則表達式這會給不正確的結果名單。如果是這樣,最好是wtite腳本。

+0

Hello Max,感謝您的答案,但我需要這個工作Arrayformula,這個不工作= arrayformula(FILTER($ F $ 2:$ F $ 4,REGEXMATCH(A2:A,$ E $ 2:$ E $ 4)))。 (在我的共享電子表格中) – user7736602

+0

'FILTER'是一個ArrayFormula本身。我在E2的公式擴展到E3和E4 –

+0

我是否錯過了一些東西,因爲使用D2:D而不是D2:D4它不起作用,因爲數據數組的大小與3不同3 – user7736602