我有一个单层嵌套数组,如下所示。
var nestedArrays = [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]];
我使用函数(by Michal Perlapowski in another question here将其展平为单个统一数组,并且比通常的reduce / concat更快,由于兼容性问题,无法使用本机flat()):
const flatten = function(arr, result = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, result);
} else {
result.push(value);
}
}
return result;
};
...
merged = flatten(nestedArrays);
这样我就可以进入下面了:
[0,1,2,3,4,5,6,7,8,9]
现在说,我的值为“ 3”,我希望从nestedArrays中找到哪个数组。 (例如,对于“ 3”,返回值“ 0”,因为它来自nestedArrays中的第0个元素数组)。我该怎么做才能最简单或最有效?
我已经尝试了几种方法来完成这项工作,例如:
1)为每个嵌套值将现有的嵌套数组转换为一对值,每个嵌套值既包含值本身,又包含父数组中嵌套数组的索引。简单但重复的数据,创建一个中间数组,以及额外的forEach循环:
var nestedArrays2 = [[0,0],[1,0],[2,0],[3,0],[4,1],[5,1],[6,1],[7,2],[8,2],[9,2]];
然后,类似地将其展平,但这将导致:
[0,0,1,0,2,0,3,0,4,1,5,1,6,1,7,2,8,2,9,2]
也可以过滤掉所有奇数值:
merged = flatten(nestedArrays2).filter((num, index) => {
return index % 2 !== 0;
})
因此,在这种情况下,我知道nestedArrays2[merged[i]][1]
将返回原始嵌套数组的索引,该数组的值与merged[i]
中的值相同,nestedArrays
处的值。
1a)分支前一个分支,但具有相同的基本思想,可以创建一个单独的数组,而无需更改原始nestedArrays
。由于我们已经遍历了它,因此我们不妨花时间在同一迭代中对其进行展平。
var merged = [];
var nestIndexes = [];
nestedArrays.forEach((element,index){
element.forEach((e) {
merged.push(e);
nestIndexes.push(index);
});
});
这将导致合并索引和嵌套索引,如下所示:
merged [0,1,2,3,4,5,6,7,8,9]
nestedIndexes [0,0,0,0,1,1,1,3,3,3]
因此,如果我在index
中得到一个值的merged
,则可以立即用nestedIndexes
从nestedIndexes[index]
中得到一个等效值
2)保留一个单独的索引引用数组
我在想,也许在合并嵌套数组之前,我可以保留一个单独的数组来标记嵌套数组开始的索引位置。只需遍历nestedArrays
,为每个元素获取length
并添加到先前的值,使其可以累加:
var nestPositions = [];
nestedArrays.forEach((element, index) {
nestPositions[index] = (element.length + (nestedArrays[index - 1] || 0) -1); //for when index is 0
})
因此,nestPositions将是:
[3,6,9]
nestedArrays
中每个嵌套数组的最后一个元素的索引。
但是在这种情况下,我得到merged[i]
之后,我将不得不每次遍历nestPositions数组以查看是否小于或等于i并中断,以检查每个元素。
3)使用nestedArrays
中的嵌套数组索引创建地图。
nestMap = new Map();
nestedArrays.forEach((element, index) => {
nestMap.set(index, element);
})
然后我可以像往常一样合并,并从merged[i]
获取元素的嵌套数组索引,我想可以在地图上进行一次forEach,就像这样:
nestMap.forEach((value, key) => {
if (value.includes(merged[i]) return key;
}
无论如何,这就是我能想到的方法。哪一个是最好的,有没有更好,更简洁的方法来解决这一问题?无论哪种方式,请感谢您的帮助,甚至只是为了达到这一目标哈哈。
答案 0 :(得分:1)
在forEach
上进行Map
会破坏使用Map
的目的。但是,如果您创建一个从元素值到其数组索引的Map
,则可以直接通过map.get(value)
获得答案:
var nestedArrays = [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]];
var merged = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var nestedIndex = new Map();
nestedArrays.forEach((nested, i) => {
nested.forEach((element, j) => nestedIndex.set(element, i));
});
console.log(nestedIndex.get(merged[0]));
console.log(nestedIndex.get(merged[3]));
console.log(nestedIndex.get(merged[5]));
console.log(nestedIndex.get(merged[9]));