【发布时间】:2016-01-14 14:54:03
【问题描述】:
我编写了以下函数来线性化任意 HTML 字符串的文本内容:
html2text(html) {
function _html2text(element, accum) {
return Array.prototype.slice.call(element.childNodes).reduce((accum, node) => {
return (node.nodeType === 3)
? `${accum} ${node.textContent}`
: _html2text(node, accum);
}, accum);
}
const div = document.createElement('div');
div.innerHTML = html;
return _html2text(div, '');
}
但现在我无法将其转换为跟踪递归样式以便对其进行优化。 我的问题是递归在减少中重复出现。 我将把它写成循环,但我无法对它进行尾部递归,这让我很生气。
这是我的循环版本:
function html2text(html) {
var div = document.createElement('div');
div.innerHTML = html;
var accum = '';
var stack = [];
stack.push([div, 0]);
while (stack.length !== 0) {
var frame = stack.pop();
var el = frame[0];
var i = frame[1];
for (; i < el.childNodes.length; i++) {
var node = el.childNodes[i];
if (node.nodeType === Node.ELEMENT_NODE) {
stack.push([el, i+1]);
stack.push([node, 0]);
break;
} else if (node.nodeType === Node.TEXT_NODE) {
accum += ' ' + node.textContent;
}
}
}
return accum;
}
这是上面用递归尾调用编写的函数,传递堆栈:
function html2text(html) {
function recurse(stack, accum) {
if (!stack.length) {
return accum;
}
var frame = stack.pop();
var el = frame[0];
var i = frame[1];
for (; i < el.childNodes.length; i++) {
var node = el.childNodes[i];
if (node.nodeType === Node.ELEMENT_NODE) {
stack.push([el, i+1]);
stack.push([node, 0]);
break;
} else if (node.nodeType === Node.TEXT_NODE) {
accum += ' ' + node.textContent;
}
}
return recurse(stack, accum)
}
var div = document.createElement('div');
div.innerHTML = html;
var stack = [];
stack.push([div, 0]);
return recurse(stack, '');
}
内部循环可以转换为另一个递归,但如果不使用不可变数据结构,这对我来说没有太大意义。
【问题讨论】:
-
有es6标签吗?由于胖箭头和尾递归是新功能,因此看起来很合适。
-
据我所知,ES6 中没有跟踪递归优化;这就是我蹦床的原因。粗箭头只是语法。
-
reduction来自哪里? -
@plalx
Array#reduce() -
搜索尾递归树遍历。
标签: javascript recursion functional-programming computer-science tail-recursion