Javascript:在创建2D数组时分配值

时间:2019-07-16 12:49:29

标签: javascript arrays multidimensional-array

这是一些Javascript代码,它们创建二维数组并用随机数填充每个单元格。

// populate 2D array with integers
const row = 5, col = 7
let pic = new Array(row).fill(0).map(item => (new Array(col).fill(0)))
for (let x = 0; x < row; x++) {
  for (let y = 0; y < col; y++) {
    pic[x][y] = Math.floor((Math.random() * 90) + 10)
  }
}

console.log(JSON.stringify(pic))

我正在寻找更“优雅”的解决方案。我的问题:

  • 是否有一种使用fill的方式来输入目标值?然后,我可以在一行中创建数组了。
  • 如何使用双.map填充2D数组,而不是双for循环?
  • 是否有一种方法可以将map / for循环的输出直接分配给变量?然后,我不需要单独的create语句。
  • 重塑数组的最佳方法是什么?例如,将1×10阵列更改为5×2阵列。
  • 有没有一种强制类型的方法?例如,第一维是字符串,第二维是整数,等等。

随时添加您自己的优雅定义。我要寻找的一件事是一种灵活的方法,该方法也可以用于3D阵列。

5 个答案:

答案 0 :(得分:3)

您可以使用嵌套的Array.from,其长度和映射功能。

const
    fn = () => Math.floor(Math.random() * 5),
    row = 5,
    col = 7,
    array = Array.from({ length: row }, () => Array.from({ length: col }, fn));

array.forEach(a => console.log(...a));

答案 1 :(得分:1)

深受启发:https://stackoverflow.com/a/53859978/9758920

const row = 5, col = 7;

let pic = [...Array(row)].map(r => [...Array(col)].map(c => ~~(Math.random()*90)+10));

console.log(pic)

答案 2 :(得分:1)

  

有没有一种方法可以使用填充值来输入目标值?然后,我可以在一行中创建数组了。

否,fill不够灵活。有Array.from(iterable, callback),但我觉得它很麻烦而且很慢。我宁愿快速编写该实用程序

function array(n, callback){
  const output = Array(n);
  for(let i=0; i<n; ++i) output[i] = callback(i);
  return output;
}
  

如何使用double .map填充2D数组,而不是double for循环?

map通过为当前Array上的每个项目调用回调函数来创建一个新的Array。您可以滥用它来使正在迭代的数组变异。您可以忽略返回数组,并将其滥用为forEach;但是map根本就是错误的工具。

var newMatrix = Array(5).fill().map(() => Array(7).fill().map(() => Math.random()));

fill部分是必需的,因为Array(length)创建了一个该长度的稀疏数组,并且map仅迭代定义的索引(即使它们包含未定义)

  

是否可以将map / for循环的输出直接分配给变量?然后,我不需要单独的create语句。

我不确定您的意思,因为您已经在此处let pic = new Array(row).fill(0).map(...)

  

重塑数组的最佳方法是什么?例如,将1×10阵列更改为5×2阵列。

function array(n, callback) {
  const output = Array(n);
  for (let i = 0; i < n; ++i) output[i] = callback(i);
  return output;
}

function toGroupsOf(n, data) {
  return array(Math.ceil(data.length / n), i => data.slice(n * i, n * (i + 1)));
}

const oneByTen = [array(10, v => v)];
console.log(oneByTen);

const twoByFive = toGroupsOf(5, oneByTen.slice().flat());
console.log(twoByFive);

  

有没有一种强制类型的方法?例如,第一维是字符串,第二维是整数,等等。

否,不在JS中。顺便说一句。除了最后一个维度之外的所有内容都是数组,而不是字符串。

但是请查看Typescript

  

随时添加您自己的优雅定义。我要寻找的一件事是一种灵活的方法,该方法也可以用于3D阵列。

// a general purpose function to create n-dimensional arrays.
// m(...dimensions, (...indices) => value)
function m(...args) {
  return args.reduceRight((cb, length) => (...indices) => {
    const output = Array(length);
    for (let i = 0; i < length; ++i)
      output[i] = cb(...indices, i);
    return output;
  })();
}

let data = m(5,7, () => Math.floor(Math.random() * 90 + 10));
console.log(data);

// 4-dimensions
console.log(m(2,3,4,5, Math.random));

// a 5x5 identity-matrix
console.log(m(5,5, (i,j) => i === j? 1: 0).join("\n"));

  

我是使用Scala之类的强类型语言的用户,例如,您永远不能在整数变量中存储字符串。我发现放任Java脚本很困难。

对此我有不同意见。我喜欢静态类型和编译时错误在我学习时(在AS3中)很少发现错误/疏忽的方式。如今,使用Typescript时,我经常觉得Typescript太自以为是了,而我自己却在考虑编译器,我知道/意味着我在这里写什么,并且更喜欢JS的灵活性。另一方面,知道我当前正在处理的对象以及它们提供的属性/方法,我仍然可以享受IDE的帮助。

答案 3 :(得分:0)

这应该有效。

const randomNumber = Math.floor((Math.random()*90)+10);
const randomMatrix = (row, col) => {
    return new Array(row).fill(randomNumber).map(item => (new Array(col).fill(randomNumber))) 
}

console.log(randomMatrix(5, 7))

答案 4 :(得分:0)

尝试下面的代码段。 initializeArray为每个单元格接受widthheightvalue的参数。

const initialize2DArray = (w, h, val = null) =>
  Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));

console.log(initialize2DArray(3, 3, 0)) // 3x3 matrix filled with zeros

如果您希望使用 N维数组,请尝试以下代码段:

const initializeNDArray = (val, ...args) =>
  args.length === 0
    ? val
    : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
    
console.log(initializeNDArray(-1, 3, 3, 3))