从一维到二维:JavaScript中的数组转换技巧

3,559 阅读3分钟

概述

在 JavaScript 中,我们经常需要将一维数组转换成二维数组。这种操作在数据处理和可视化等领域非常常见。本文将介绍两种将一维数组转换成二维数组的方法,希望能够帮助读者更好地理解这一过程。

方法一:使用循环

最基本的方法是使用循环遍历一维数组,然后将每个元素插入到二维数组的相应位置。下面是一个使用循环的示例代码:

function convertArray(arr, rows, columns) {
  var result = [];
  for (var i = 0; i < rows; i++) {
    result[i] = [];
    for (var j = 0; j < columns; j++) {
      var index = i * columns + j;
      if (index < arr.length) {
        result[i][j] = arr[index];
      }
    }
  }
  return result;
}

上面的代码中,convertArray 函数接收三个参数:原始一维数组 arr,新数组的行数 rows 和新数组的列数 columns。函数首先创建一个空的二维数组 result,然后使用两个嵌套循环将每个元素插入到相应的位置。

在内部循环中,我们计算当前元素在一维数组中的索引 index。如果 index 小于原始数组的长度,则将原始数组中的对应元素插入到二维数组的当前位置。

使用循环的好处是代码简单,易于理解。但是,这种方法可能不够高效,特别是对于非常大的数组。

方法二:使用高阶函数

另一种将一维数组转换成二维数组的方法是使用 JavaScript 数组的高阶函数。下面是一个使用 reduceslice 方法的示例代码:

function convertArray(arr, rows, columns) {
  return arr.reduce(function(result, item, index) {
    var rowIndex = Math.floor(index / columns);
    var colIndex = index % columns;
    if (!result[rowIndex]) {
      result[rowIndex] = [];
    }
    result[rowIndex][colIndex] = item;
    return result;
  }, []);
}

上面的代码中,我们使用 reduce 方法遍历原始数组 arr,然后将每个元素插入到新的二维数组中。在每次迭代中,我们计算当前元素在二维数组中的行列位置 rowIndexcolIndex,然后使用 if 语句检查二维数组中是否已经存在这一行。如果不存在,则创建一个新的行,然后将当前元素插入到对应的位置。

使用高阶函数的好处是代码更加简洁,且对于大型数组可以提高效率。同时,它也可以让我们使用更高阶的函数,如 mapflatMap 等,可以更加简化代码,提高可读性和可维护性。下面是一个使用 flatMap 方法的示例代码:

function convertArray(arr, rows, columns) {
  return arr.flatMap((item, index) =>
    index % columns ? [] : [arr.slice(index, index + columns)]
  );
}

上面的代码中,我们使用 flatMap 方法遍历原始数组 arr,然后对于每个元素 item,判断它在新数组中的位置。如果是新的一行,则使用 slice 方法将该行的元素提取出来,然后返回该行。否则,返回一个空数组。

示例

力扣题解 第13期:2022. 将一维数组转变成二维数组

var construct2DArray(original, m, n) {
  const len = original.length;
  if (len !== m * n) {
    return [];
  }
  const res = new Array(m);
  for (let i = 0; i < m; i++) {
    res[i] = original.slice(i * n, (i + 1) * n);
  }
  return res;
}

该函数接收一个一维数组 original,和两个整数 mn。它首先检查 original 的长度是否等于 m * n,如果不等于则返回一个空的二维数组。如果长度等于 m * n,则创建一个二维数组 res,然后使用 for 循环将 original 中每 n 个元素分为一行,最后返回创建好的二维数组 res

这种方法的时间复杂度为 O(mn)O(mn),空间复杂度为 O(m)O(m)

var construct2DArray = function (original, m, n) {
    return original.length !== m * n ? [] : new Array(m).fill(0).map((v, i) => {
        return original.slice(n * i, n * i + n);
    });
};

这个方法使用了条件运算符(ternary operator)和数组的 map() 方法来实现创建二维数组。具体来说,它首先检查 original 的长度是否等于 m * n,如果不等于则返回一个空的二维数组 []。如果长度等于 m * n,则使用 map() 方法创建一个长度为 m 的新数组,每个元素都通过一个函数映射成一个长度为 n 的新数组,新数组的元素从 original 中截取出来。

这个函数的第二个参数 i 代表 map() 方法内部当前处理的元素的下标,它用来计算当前行的起始下标,即 n * i。然后使用 slice() 方法从 original 中截取出对应的元素。具体来说,对于第 i 行,它的元素从 n * i 开始,到 n * i + n - 1 结束。因此,可以使用 slice(n * i, n * i + n) 来截取这一行的元素。

这种方法使用了数组的高阶函数 map() 方法,代码简洁易读,可维护性较好。时间复杂度为 O(mn)O(mn),空间复杂度为 O(m)O(m)

var construct2DArray = function(original, m, n) {
    return original.length === m * n ? 
        Array.from({ length: m }, (_, i) => original.slice(i * n, (i + 1) * n)) : 
        [];
};

这个方法使用了 Array.from() 方法和箭头函数,使代码更加简洁。具体来说,它首先检查 original 的长度是否等于 m * n,如果不等于则返回一个空的二维数组 []。如果长度等于 m * n,则使用 Array.from() 方法创建一个长度为 m 的新数组,并通过箭头函数将每个元素映射成一个长度为 n 的新数组,这个新数组的元素从 original 中截取出来。最后返回这个新的二维数组。

这种方法的时间复杂度为 O(mn)O(mn),空间复杂度为 O(m)O(m)

总结

在本文中,我们介绍了两种将一维数组转换成二维数组的方法。第一种方法使用循环,第二种方法使用 JavaScript 的高阶函数。使用循环的代码比较简单,但是可能不够高效;使用高阶函数的代码更加简洁,可读性和可维护性更好,对于大型数组也有一定的性能优势。

如果你需要将一维数组转换成二维数组,可以根据实际情况选择合适的方法。希望本文能够帮助你更好地理解 JavaScript 中数组的处理和转换技巧。