[英]Converting Javascript solution to Functional Programming Approach
最近,我(非常)對函數式編程非常感興趣,尤其是如何將其應用於我的JavaScript工作。 在回答了有關正則表達式使用的問題之后(我在這里 ,鏈接),我繼續進行更多的構想,以將其與功能性編程方法進行比較。
面臨的挑戰是編寫一個簡單的輸入解析器,該解析器接受一個正則表達式和一些輸入並返回匹配的對象數組(這是更大解決方案的步驟1,但我想從簡單開始)。 我可以使用更傳統的方法來使用它,但是想對功能編程做同樣的事情(我使用的是ramda.js,但只要是JavaScript,就可以使用任何功能編程方法)。
這是工作代碼:
var parseInput = function (re, input) {
var results = [], result;
while ((result = re.exec(input)) !== null) {
results.push({
startPos: result.index,
endPos: re.lastIndex - 1,
matchStr: result[1]
})
}
return results;
};
var re = /<%([^%>]+)%>/g;
var input = "A <%test.child%><%more%> name: <%name%> age: <%age%> EOD";
var results = parseInput(re, input);
console.log(results);
我得到的輸出看起來像這樣:
[ { startPos: 2, endPos: 15, matchStr: 'test.child' },
{ startPos: 16, endPos: 23, matchStr: 'more' },
{ startPos: 31, endPos: 38, matchStr: 'name' },
{ startPos: 45, endPos: 51, matchStr: 'age' } ]
這是我要尋找的結構和結果。
特別是,我一直在嘗試使用Ramda和'match()'函數,但是我看不到一種干凈的方法來獲取想要的對象數組(缺少運行match()來獲取數組)的方法。匹配項,然后在原始輸入中查找每個匹配項,這似乎比我當前的解決方案麻煩得多)。
指導將不勝感激。
沒錯,Ramda的match
不會為您提供幫助。 專為更簡單的用途而設計。 我認為沒有什么比您的代碼更好的了,盡管我可能會有所不同:
const execAll = R.curry((re, convert, input) => {
let results = [], result;
while ((result = re.exec(input))) {
results.push(convert(result))
}
return results;
});
const parseInput = execAll(/<%([^%>]+)%>/g, match => ({
startPos: match.index,
endPos: match.index + match[0].length - 1,
matchStr: match[1]
}));
const input = "A <%test.child%><%more%> name: <%name%> age: <%age%> EOD";
parseInput(input);
顯然,此代碼的結構不同,將regex exec
調用的循環與輸出格式分開。 不過,更巧妙的是,它也不依賴於正則表達式的全局狀態,僅將返回的match
結果中的信息用於其輸出。 這對我來說對函數式編程很重要。
Ramda curry
招牌是純肉汁。 您也可以這樣寫
const execAll = (re, convert) => (input) => { /* ... */ }
如果您有興趣,可以在Ramda REPL上使用。
請注意,這與您的方法相比並沒有太大變化。 我沒有看到適用於一系列正則表達式的明顯不同的方法。
只需稍微更改您的正則表達式,就可以使用String.prototype.match()
方法執行以下操作:
var str = "A <%test.child%><%more%> name: <%name%> age: <%age%> EOD", rex = /[^<%]+(?=%>)/g, res = str.match(rex); console.log(res);
好吧,如果您一直使用這種嚴格的regex條件結構,那么您可以考慮使用非regex功能代碼以更快的方式完成相同的工作,如下所示;
var str = "A <%test.child%><%more%> name: <%name%> age: <%age%> EOD", res = Array.prototype.reduce.call(str, function(r,c,i,s){ c === "%" && s[i-1] === "<" ? (r.select = true, r.push({startPos:i+1, endPos:undefined, matchStr: ""})) : c === ">" && s[i-1] === "%" ? (r.select = false, r[r.length-1].endPos = i-2) : r.select && c !== "%" && (r[r.length-1].matchStr.length ? r[r.length-1].matchStr += c : r[r.length-1].matchStr = c); return r; },[]); console.log(res);
您會注意到開始位置和結束位置與您的示例有所不同,這僅僅是因為它們給出了匹配子字符串的真實開始位置和結束位置。 您可以輕松地更改代碼以包括<%
和%>
的索引。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.