简体   繁体   English

在创建二维数组时分配值

[英]Assigning values whilst creating a 2D array

Here is some Javascript code that creates a 2-dimension array and fills each cell with a random number.这是一些创建二维数组并用随机数填充每个单元格的 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))

I'm looking for a more 'elegant' solution.我正在寻找更“优雅”的解决方案。 My questions:我的问题:

  • Is there a way to use the fill so that I can put in my target values?有没有办法使用fill来输入目标值? Then I can be finished with creating the array in one line.然后我可以在一行中完成创建数组。
  • How do I use a double .map to populate the 2D array, instead of a double for loop?如何使用双.map填充二维数组,而不是双for循环?
  • Is there a way to assign the output from the map / for loops directly into a variable?有没有办法将map / for循环的输出直接分配给变量? Then I don't need a separate create statement.然后我不需要单独的 create 语句。
  • What is the best way to reshape an array?重塑数组的最佳方法是什么? For example, changing a 1-by-10 array into a 5-by-2 array.例如,将 1×10 数组更改为 5×2 数组。
  • Is there a way to enforce a type?有没有办法强制执行类型? For instance the first dimension is a string, 2nd is an integer, etc.例如第一个维度是一个字符串,第二个维度是一个整数,等等。

Feel free to add your own definition of elegance.随意添加您自己对优雅的定义。 One of the things I'm looking for is a flexible approach that can also work with 3D arrays.我正在寻找的一件事是一种灵活的方法,它也可以与 3D 数组一起使用。

You could take a nested Array.from with a length and a mapping function.您可以使用具有长度和映射函数的嵌套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));

Heavily inspired by: https://stackoverflow.com/a/53859978/9758920深受启发: 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)

Is there a way to use the fill so that I can put in my target values?有没有办法使用填充来输入目标值? Then I can be finished with creating the array in one line.然后我可以在一行中完成创建数组。

No, fill is not that flexible.不, fill不是那么灵活。 There is Array.from(iterable, callback) but I find it cumbersome and it is slow.Array.from(iterable, callback)但我觉得它很麻烦而且很慢。 I'd rather write that utility quickly我宁愿快速编写该实用程序

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

How do I use a double .map to populate the 2D array, instead of a double for loop?我如何使用双 .map 来填充二维数组,而不是双循环?

map creates a new Array, by calling the callback function for each item on the current Array. map通过为当前 Array 上的每个项目调用回调函数来创建一个新 Array。 You can abuse it to mutate the Array that is iterating.您可以滥用它来改变正在迭代的 Array。 You can ignore the returnes Array and abuse it as forEach ;您可以忽略返回数组并将其作为forEach滥用; but then map simply is the wrong tool.但是map只是错误的工具。

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

the fill part is necessary, because Array(length) creates a sparse Array of that length and map only iterated defined indices (even if they contain undefined) fill部分是必要的,因为Array(length)创建了一个该长度的稀疏数组并且只map迭代定义的索引(即使它们包含未定义)

Is there a way to assign the output from the map / for loops directly into a variable?有没有办法将 map/for 循环的输出直接分配给变量? Then I don't need a separate create statement.然后我不需要单独的 create 语句。

I'm not sure what you mean, because you already do that here let pic = new Array(row).fill(0).map(...)我不确定你的意思,因为你已经在这里做了let pic = new Array(row).fill(0).map(...)

What is the best way to reshape an array?重塑数组的最佳方法是什么? For example, changing a 1-by-10 array into a 5-by-2 array.例如,将 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);

Is there a way to enforce a type?有没有办法强制执行类型? For instance the first dimension is a string, 2nd is an integer, etc.例如第一个维度是一个字符串,第二个维度是一个整数,等等。

No, not in JS.不,不是在 JS 中。 btw.顺便提一句。 everything but the last dimension will be Arrays, not String.除了最后一个维度之外的所有内容都是数组,而不是字符串。

But check out Typescript .但请查看Typescript

Feel free to add your own definition of elegance.随意添加您自己对优雅的定义。 One of the things I'm looking for is a flexible approach that can also work with 3D arrays.我正在寻找的一件事是一种灵活的方法,它也可以与 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"));

I'm a user of strongly typed languages like Scala, where for instance, you could never store a string in an integer variable.我是 Scala 等强类型语言的用户,例如,您永远无法将字符串存储在整数变量中。 I find the laissez faire of Javascript difficult.我发现 Javascript 的自由放任很困难。

I have mixed opinions on that.我对此意见不一。 I loved the way that static types and compile-time errors found little mistakes/oversights back when I learned (in AS3).我喜欢静态类型和编译时错误在我学习时发现很少错误/疏忽的方式(在 AS3 中)。 Nowadays and with Typescript I often find Typescript to be too opinionated and find myself thinking f off compiler, I know/mean what I'm writing here and prefer the flexibility of JS.如今,使用 Typescript,我经常发现 Typescript 过于固执,并且发现自己在考虑编译器,我知道/意味着我在这里写的是什么,并且更喜欢 JS 的灵活性。 On the other hand, I still enjoy the assistance that comes from the IDE knowing what Objects I'm currently dealing with and what properties/methods they provide.另一方面,我仍然喜欢 IDE 提供的帮助,因为我知道我当前正在处理哪些对象以及它们提供哪些属性/方法。

This should work.这应该有效。

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))

Try the snippet below.试试下面的片段。 initializeArray accepts parameters for width , height and a value for each cell. initializeArray接受widthheight参数和每个单元格的value

 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

If you prefer a N-dimension array, try the snippet below:如果您更喜欢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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM