2017-05-25 29 views
1

我想編寫一個函數,例如:提取值給出一個簡單的模板

function extract(template, example){ 
    //some magic 
    return obj; 
} 

,鑑於類似下面的輸入:

var template = "/some/path/{param_one}/{another_param}/etc?arg1={value}"; 
var example = "/some/path/foo/bar/etc?arg1=baz"; 

將返回該對象:

{param_one: "foo", another_param: "bar", value: "baz"} 

我對模板和示例沒有控制權(例如,我不能將模板更改爲re gex與命名捕獲組)。我可以安全地假設的是,給定的例子將匹配模板。

作爲一個開始,我能夠用這種提取鍵:

var re = /\{(.+?)\}/g; 
var match; 
do { 
    match = re.exec(template) 
    if (match) { 
     console.log(match[1]); 
    } 
} while (match); 
+0

的問題沒有得到很好的指定splited參數數組和匹配值。 'template =「{param_one} {param_two}」的結果是什麼? example =「abc」;'?或者'template =「{param_one}/{param_two}」; example =「///」'?如果你的輸入總是url路徑+查詢,那麼它將是可以解決的。 –

+0

@le_m,你是對的。你可以假定它總是一個路徑和查詢,並且兩個模板變量總是至少用'/','''或'&分開。儘管也應該接受以下內容:'{param_a}/prefix {param_b} /' – Seba

回答

1

我用正則表達式和替換來解決:

function extract(template, example){ 
    //some magic 
    var re = /(?:([^\{]*)\{([^\}]*)\})/g; 
    var result = example; 
    var params = []; 
    var match, values, obj = {}; 
    do { 
    match = re.exec(template) 
    if (match) { 
     result = result.replace(match[1], '|'); 
     params.push(match[2]); 
    } 
    } while (match); 
    values = result.split('|'); 
    for(var i=0;i < params.length; i++) { 
    obj[params[i]] = values[i+1]; 
    } 
    return obj; 
} 

首先,它得到PARAMS部分和文字部分使用正則表達式,然後將其與|和存儲鍵替換所有文字部分參數數組。

最後,它遍歷從上面

希望這有助於

+0

謝謝!我喜歡你如何解決它! – Seba

0

我會打破這個分爲兩個部分 - 建立一個模板對象,然後使用該模板對象來解析你的字符串(S) 。以下函數buildTemplate(pattern)返回一個模板對象。然後,您可以使用此對象根據需要解析任意數量的字符串,例如buildTemplate(pattern).parse(string)甚至var parser = buildTemplate(pattern); var parameters = parser.parse(string);

function buildTemplate(pattern) { 
    return (function(pattern) { 
     function splitString(string) { 
      return string.split(/[/?&]+/); 
     } 

     var glob = {}; 

     glob.parts = splitString(pattern).map(function(part) { 
      var trimmedPart = part.replace(/^\{|\}$/g, ''); 
      var isLiteral = part.length !== trimmedPart.length + 2; 

      return { 
       isLiteral: isLiteral, 
       value: isLiteral ? part : trimmedPart: 
      }; 
     }); 

     glob.parse = function(string) { 
      var stringParts = splitString(string); 

      if (stringParts.length !== glob.parts.length) { 
       return null; 
      } 

      var params = {}; 

      for (var i = 0; i < stringParts.length; i++) { 
       if (blob.parts[i].isLiteral) { 
        if (blob.parts[i].value !== stringParts[i]) { 
         return null; 
        } 
       } else { 
        params[blob.parts[i].value] = stringParts[i]; 
       } 
      } 

      return params; 
     } 

     return glob; 
    })(pattern); 
} 

注:此代碼是完全未經測試。讓我知道,如果有什麼不按預期工作。