如何按多个判定函数最优拆分数组?求对应算法或可用JS库
实现方案
目前没有专门实现该定制化拆分逻辑的公开第三方库,由于你的场景数据量极小,直接暴力枚举所有合法拆分方案后按规则排序选最优即可,以下是可直接使用的JS实现:
逻辑前提
- 拆分的子数组数量等于传入的判定函数数量,第
i个子数组对应第i个判定函数 - 子数组为原数组的连续切片,元素顺序保持和原数组一致
代码实现
function specialFunc(list, predicates) { const k = predicates.length; const n = list.length; // 边界情况:段数不能大于数组长度 if (k <= 0 || n < k) return []; // 生成所有可能的拆分位置组合:k段需要k-1个拆分点,拆分点严格递增 const allSplits = []; function generateSplits(start, current) { if (current.length === k - 1) { allSplits.push([...current]); return; } for (let i = start; i < n - (k - 1 - current.length); i++) { current.push(i); generateSplits(i + 1, current); current.pop(); } } generateSplits(1, []); // 给每个拆分方案打分 const scored = allSplits.map(splitPos => { // 按拆分点切分子数组 const segments = []; let prev = 0; for (const pos of splitPos) { segments.push(list.slice(prev, pos)); prev = pos; } segments.push(list.slice(prev)); // 第一优先级打分:子数组长度差值(最大-最小),越小越优 const lengths = segments.map(s => s.length); const lengthDiff = Math.max(...lengths) - Math.min(...lengths); // 第二优先级打分:匹配判定函数的元素总数,越大越优 let matchCount = 0; segments.forEach((seg, idx) => { const predicate = predicates[idx]; seg.forEach(item => { // 若判定函数需要直接判断整个item,可删掉.gender if (predicate(item.gender)) matchCount++; }) }) return { segments, lengthDiff, matchCount }; }) // 按规则排序取最优 scored.sort((a, b) => { if (a.lengthDiff !== b.lengthDiff) return a.lengthDiff - b.lengthDiff; return b.matchCount - a.matchCount; }) return scored[0].segments; }
测试验证
const list = [{gender: "female"}, {gender: "female"}, {gender: "female"}, {gender: "male"}] // 测试用例1 console.log(specialFunc(list, [(val) => val === 'female', (val) => val === 'male'])); // 输出 [[{gender:"female"},{gender:"female"},{gender:"female"}],[{gender:"male"}]] // 测试用例2 console.log(specialFunc(list, [(val) => !!val, (val) => val === 'male'])); // 输出和用例1完全一致
内容的提问来源于stack exchange,提问作者Nevo David
相关产品推荐
相关产品推荐

