展平后,将元素的索引保留在嵌套数组中

时间:2019-10-01 15:39:37

标签: javascript arrays dictionary multidimensional-array

我有一个单层嵌套数组,如下所示。

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,则可以立即用nestedIndexesnestedIndexes[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;
}

无论如何,这就是我能想到的方法。哪一个是最好的,有没有更好,更简洁的方法来解决这一问题?无论哪种方式,请感谢您的帮助,甚至只是为了达到这一目标哈哈。

1 个答案:

答案 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]));