我有这个数组包含两个子集7,8和1两次:
[
[1,2],
[9,10,7,8],
[5,6,7,8],
[1]
]
如何在此数组中找到并提取所有子集(包含多次,即不是自身)并得到以下结果?
[
[2],
[9,10],
[7,8],
[5,6],
[1]
]
子集总是连续的,即9,7不应被视为9,10,7,8的子集。
修改 最终数组的顺序无关紧要,但项目应该与起始数组相似:
ok=[ ok=[ notOk=[
[2], [9,10], [10,9],
[9,10], [2], [2],
[7,8], [5,6], [6,5],
[5,6], [1], [1],
[1] [7,8] [8,7]
] ] ]
非常感谢任何非递归解决方案。
答案 0 :(得分:1)
您可以使用地图作为常用项目。从地图中删除具有单个计数的项目,使用地图首先构建公共结果集。然后在检查是否常见后使用其余的结果集,然后返回或检查是否连续,追加到最后的结果集,或者将新数组添加到结果集。
var data = [[1, 2], [9, 10, 7, 8], [5, 6, 7, 8], [1]],
result = [],
common = new Map;
// get all items and store the occurence
data.forEach((a, i) => a.forEach(b => {
if (!common.has(b)) {
common.set(b, []);
}
common.get(b).push(i);
}));
// keep only occurence of more then one
common.forEach((v, k, m) => v.length === 1 && m.delete(k));
// get common keys, sort and push single or contiguous elements to the result set
[...common.keys()].sort((a, b) => a - b).forEach((k, i, kk) => {
var l = kk[i - 1];
if (l === k - 1 && common.get(l).toString() === common.get(k).toString()) {
result[result.length - 1].push(k);
return;
}
result.push([k]);
});
// push non common items to the result set
data.forEach((a, i) => a.forEach(function (b, i, bb) {
var l = bb[i - 1];
if (common.has(b)) {
return;
}
if (!common.has(l) && l === b - 1) {
result[result.length - 1].push(b);
return;
}
result.push([b]);
}));
console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:1)
我建议这个解决方案为每个不同的值构建一个map(哈希),为它提供一系列的出现。每个这样的数组元素提供发生值的子数组(来自输入),以及它在该子数组中的索引。
在第二步中,比较等值元素的后继者。如果那些也是相同的,并且该值不会出现在任何其他地方(即具有不同的前任),那么可以得出结论,后继值应该与前面的值保持连接。当这种情况发生时,接下来的后继者将接受测试,看看是否可以形成一个完整的三元组,等等。
在下面的代码中,我使用了与问题中提供的输入数据不同的输入数据,因为与其他解决方案(我之前发布的)相比,此解决方案产生的输出数据不同。
代码使用ES6语法:
var input = [
[1,3],
[9,11,7,12,2],
[5,0,7,12,2,8,10,7,12,2],
[1]
];
// build hash (map)
var hash = input.reduce ( (hash, arr) =>
arr.reduce ( (hash, val, index) =>
// Collect the array element's references in a Map keyed by value:
hash.set(val, (hash.get(val) || []).concat({ arr, index })),
hash
), new Map() // initial value of the hash is an empty Map
);
var result = Array.from(hash, ([val, matches]) => {
var match = matches[0];
// Compare the sucessors of the elements that are equal
for (var offset = 1; match.index + offset < match.arr.length; offset++) {
var valAtOffset = match.arr[match.index+offset];
// If the sucessor values only occur as successor of the preceding value,
// and all these successors have the same value, then keep this value together
// with the preceding value:
if (hash.get(valAtOffset).length !== matches.length ||
matches.some( match => match.arr[match.index+offset] !== valAtOffset )) break;
// Remove the hash entry for the value that is now part of this unbroken sequence
hash.delete(valAtOffset);
}
return match.arr.slice(match.index, match.index+offset);
});
// output:
console.log(JSON.stringify(result));
&#13;