javascript - JavaScript 将原始数组保留在递归函数中
问题描述
我想保留原始数组以在递归函数中返回原始索引。原始代码来自 rbarilani https://gist.github.com/rbarilani/0d7946510740f9e1e8fa。请帮忙告知如何更改线路
const numList = [3,9,8,4,5.5,7,10.07];
function subsetSum(numbers, target, partial) {
var s, n, remaining;
const numList = [3,9,8,4,5.5,7,10.07]; **//<<<<<<<The code I want to change, please advise how to make it as function input**
partial = partial || [];
// sum partial
s = partial.reduce(function (a, b) {
return Math.round((a + b)*100)/100;
}, 0);
// check if the partial sum is equals to target
if (s === target) {
console.log(numList);
partial.forEach(function(findIndex){
console.log(findIndex, 'is at position ', numList.indexOf(findIndex));
});
}
for (var i = 0; i < numbers.length; i++) {
n = numbers[i];
remaining = numbers.slice(i + 1);
subsetSum(remaining, target, partial.concat([n]));
}
}
subsetSum([3,9,8,4,5.5,7,10.07],15.57);
谢谢你们
解决方案
我会推荐生成器,因为它们非常适合此类问题。生成器的好处是它是可暂停和可取消的。这使您可以轻松找到问题的一种解决方案或所有解决方案,而无需更改代码。
function* subsetSums(numbers, target, precision = 2)
{ function* solve(i, q, r)
{ if (q == 0) return yield r
if (numbers.length < i || q < 0) return
// solve with this number
yield *solve
( i + 1
, round(q - numbers[i], precision)
, [...r, {pos: i, n: numbers[i]}]
)
// solve without this number
yield *solve(i + 1, q, r)
}
yield *solve(0, target, [])
}
注意我是如何分离round
成它自己的功能的。隔离关注点是一种有效的编程技术,因为它使您的函数更易于读/写,并促进了程序其他区域内的代码重用
const round = (n, p = 0) =>
Math.round(n * 10 ** p) / 10 ** p
我们可以得到所有的解决方案——
const solutions =
Array.from(subsetSums([3.27,9,8,6.8,4,5.5,7,10.07], 15.57))
或者,也许我们只是想要first
解决方案。因为生成器是可取消的,这意味着在返回第一个值后不会做任何工作——
function first (it)
{ for (const v of it)
return v
}
const solution =
first(subsetSums([3.27,9,8,6.8,4,5.5,7,10.07], 15.57))
form
我们可以使用一些额外的通用函数将其包装到一个简单的 HTML中stepper
,它会逐步执行任何生成器,并且json
它会创建一个带有JSON.stingify
'd 内容的文本节点 -
function* stepper (it, f)
{ let x = it.next()
while (!x.done) (yield f(x.value), x = it.next())
while (true) yield f("no more results")
}
function json(value)
{ const e = document.createElement("pre")
e.textContent = JSON.stringify(value)
return e
}
现在我们要做的就是将它连接到我们的表单 -
<form id="solver">
<button type="button" name="next">next</button>
<output name="output"></output>
</form>
const f =
document.forms.solver
const solver =
stepper
( subsetSums([3.27,9,8,6.8,4,5.5,7,10.07], 15.57)
, solution =>
f.output.appendChild(json(solution))
)
f.next.addEventListener("click", _ => solver.next())
运行下面的代码片段以在您自己的浏览器中查看结果 -
function* subsetSums(numbers, target, precision = 2)
{ function* solve(i, q, r)
{ if (q == 0) return yield r
if (numbers.length < i || q < 0) return
// solve with this number
yield *solve
( i + 1
, round(q - numbers[i], precision)
, [...r, {pos: i, n: numbers[i]}]
)
// solve without this number
yield *solve(i + 1, q, r)
}
yield *solve(0, target, [])
}
function* stepper (it, f)
{ let x = it.next()
while (!x.done) (yield f(x.value), x = it.next())
while (true) yield f("no more results")
}
function json(value)
{ const e = document.createElement("pre")
e.textContent = JSON.stringify(value)
return e
}
const round = (n, p = 0) =>
Math.round(n * 10 ** p) / 10 ** p
const f =
document.forms.solver
const solver =
stepper
( subsetSums([3.27,9,8,6.8,4,5.5,7,10.07], 15.57)
, solution =>
f.output.appendChild(json(solution))
)
f.next.addEventListener("click", _ => solver.next())
<form id="solver">
<button type="button" name="next">next</button>
<output name="output"></output>
</form>
[{"pos":0,"n":3.27},{"pos":3,"n":6.8},{"pos":5,"n":5.5}]
[{"pos":5,"n":5.5},{"pos":7,"n":10.07}]
"no more results"
numbers
输入不会因为运行而被修改subsetSums
。
推荐阅读
- r - ggplot2 声称 `inherit` 必须是 R6ClassGenerator
- php - 如果 IF 语句为 True,则跳过 array_map 函数的迭代
- sql - 不等于主键的外键上的 SQL JOIN
- unreal-engine4 - 打开后无法关闭舱口
- angular - 异步管道在 Angular 6 中获取 [object Object]
- r - 如何从 R 中的 ggplot2 统计摘要中提取置信区间的值?
- python - 如何检查 Pyspark 中的计数值?
- vba - 如何为字符串中定义的变量赋值?
- c# - Excel 文本到 C# 数据表中的列等效项
- android - 找不到与给定名称匹配的资源 dialogCornerRadius