如何进一步优化ES6实现的子集和近似匹配代码?
背景
我有一组商品价格数据,需要找到最接近目标数值的购买组合。原本的思路是生成所有可能的购买组合(用布尔序列表示),再计算各组合的和,从中找出最接近目标值的组合。示例如下:
- 示例数据集:
$10, $5, $1 - 目标值:
$12 - 布尔序列组合:
001, 010, 100, 011, 101, 110, 111 - 各组合和:
$1, $5, $10, $6, $11, $15, $16 - 最接近的布尔序列为
101,对应和为$11
问题
数据集较小时,用ES6实现的代码运行正常,但数据量增加后,处理时间呈指数级增长。不更换编程语言的前提下,有哪些改进方法能缩短处理时间?
当前遇到性能瓶颈的数据集:
- data:
[7524.00,1.63,2000.00,23794.00,0.01,330.00,462.00,858.00,5000.00,5250.00,23162.00,23804.00,5250.00,13376.00,0.06,0.08,4000.00,10000.00,166.56,12441.00,25.00,1000.00,20000.00,2000.00,20000.00,10000.00,5468.00,20000.00]; - target:
201887
当前代码
let possibles = []; let sums = []; let target = 201887; let data = [7524.00,1.63,2000.00,23794.00,0.01,330.00,462.00,858.00,5000.00,5250.00,23162.00,23804.00];//,5250.00,13376.00,0.06,0.08,4000.00,10000.00,166.56,12441.00,25.00,1000.00,20000.00,2000.00,20000.00,10000.00,5468.00,20000.00]; let rep = new Array(data.length).fill(1).join(''); let decMax = b2d(rep) + 1; genPossibles(decMax, possibles) .then(genSums() .then(matchTarget())); /**************** functions ****************/ function d2b(d){ return Number(d).toString(2); } function b2d(b) { return parseInt(b, 2); } function genPossibles(decMax, arr, start=0, runs=1000) { return new Promise((resolve, reject) => { //console.log(decMax, arr.length, start, runs); for(let i = start; i < start+runs; ++i) { if(start+i > decMax) { possibles.pop(); // last item is useless console.log("possibles", possibles.length); resolve(); return; } let binStr = d2b(i); possibles.push(binStr); } setTimeout(() => genPossibles(decMax, arr, start+runs), 0); }); } function genSums(start=0, runs=1000) { return new Promise((resolve, reject) => { for(let i = start; i < start+runs; ++i) { if(i >= possibles.length) { console.log("sums", sums.length); resolve(); return; } let str = possibles[i]; let sum = 0; str.split('').reverse().forEach((bool, j) => { if(bool == 1) sum += +data[j]; }); sums.push(sum); } setTimeout(() => genSums(start+runs), 0); }); } function matchTarget() { let closest = {id:-1, bin: '', total:-1, diff:Infinity}; sums.forEach((o, i) => { let d = Math.abs(target - o); if(d < closest.diff) { closest.id = i; closest.bin = possibles[i]; closest.total = o; closest.diff = d; } }); console.log("closest", closest); }
补充说明
目前暂时注释了部分数据,待找到优化方案后再启用完整数据集。
内容的提问来源于stack exchange,提问作者Jacksonkr
相关产品推荐
相关产品推荐

