如何递归复制阵列

发布于 2025-01-21 11:21:32 字数 1068 浏览 0 评论 0原文

我想递归产生单位n-hypercube的顶点(为了清楚起见,只是一个立方体)。这个想法是通过递归通过X,Y和Z组件来指定立方体的点。为什么不使用嵌套的for呢?递归本质上是赃物。这是我的功能:

var points = [];

function makeCube(d, point) {
  console.log(d,point);
  
  if(d == 0) {
    points.push(point);
  } else {
    extension1 = [...point];
    extension1.push(0);

    extension2 = [...point];
    extension2.push(1);
    
    makeCube(d - 1, extension1);
    makeCube(d - 1, extension2);
  }
}

我调用makeCube(3,[])。控制台读取以下内容:

[Log] 3 – [] (0) (sketch.js, line 57)
[Log] 2 – [0] (1) (sketch.js, line 57)
[Log] 1 – [0, 0] (2) (sketch.js, line 57)
[Log] 0 – [0, 0, 0] (3) (sketch.js, line 57)
[Log] 0 – [0, 0, 1] (3) (sketch.js, line 57)
[Log] 1 – [0, 0, 1] (3) (sketch.js, line 57)
[Log] 0 – [0, 0, 1, …] (4) (sketch.js, line 57)
etc...

当D为1时,数组中只有2个条目,而不是3个条目!当d为0时,应该有3个,而不是4。最低级别的第二个阵列以某种方式提高了一个水平。我提出了复制扩展阵列而不是将它们设置为旧数组,所以我不明白发生了什么。

预期控制台输出:

[]
[0]
[0,0]
[0,0,0]
[0,0,1]
[0,1]
[0,1,0]
[0,1,1]
[1]
[1,0]
[1,0,0]
[1,0,1]
[1,1]
[1,1,0]
[1,1,1]

I want to recursively produce the vertices (points) of a unit n-hypercube (for the sake of clarity, just a cube here). The idea is to specify the points of the cube by recursively going through the x, y, and z components. Why not just use nested for-loops? Recursion is intrinsically swag. This is my function:

var points = [];

function makeCube(d, point) {
  console.log(d,point);
  
  if(d == 0) {
    points.push(point);
  } else {
    extension1 = [...point];
    extension1.push(0);

    extension2 = [...point];
    extension2.push(1);
    
    makeCube(d - 1, extension1);
    makeCube(d - 1, extension2);
  }
}

I call makeCube(3, []). The console reads this:

[Log] 3 – [] (0) (sketch.js, line 57)
[Log] 2 – [0] (1) (sketch.js, line 57)
[Log] 1 – [0, 0] (2) (sketch.js, line 57)
[Log] 0 – [0, 0, 0] (3) (sketch.js, line 57)
[Log] 0 – [0, 0, 1] (3) (sketch.js, line 57)
[Log] 1 – [0, 0, 1] (3) (sketch.js, line 57)
[Log] 0 – [0, 0, 1, …] (4) (sketch.js, line 57)
etc...

When d is 1, there should only be 2 entries in the array, not 3! When d is 0, there should be 3, not 4. The second array in the lowest level is being carried up a level somehow. I made a point of copying the extension arrays rather than setting them equal to the old one, so I don't understand what's going on.

Expected console output:

[]
[0]
[0,0]
[0,0,0]
[0,0,1]
[0,1]
[0,1,0]
[0,1,1]
[1]
[1,0]
[1,0,0]
[1,0,1]
[1,1]
[1,1,0]
[1,1,1]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

屋顶上的小猫咪 2025-01-28 11:21:32

我想我解决了这个问题:

var points = [];

function makeCube(d, point) {
  console.log(d, JSON.stringify(point));
  
  if(d == 0) {
    points.push([...point]);
  } else {
    let extension1 = [...point];
    extension1.push(0);

    let extension2 = [...point];
    extension2.push(1);
    
    makeCube(d - 1, extension1);
    makeCube(d - 1, extension2);
  }
}

makeCube(3, [])

3 []
2 [0]
1 [0,0]
0 [0,0,0]
0 [0,0,1]
1 [0,1]
0 [0,1,0]
0 [0,1,1]
2 [1]
1 [1,0]
0 [1,0,0]
0 [1,0,1]
1 [1,1]
0 [1,1,0]
0 [1,1,1]

我刚刚添加了Let两次(并更改了我记录的内容)。
原始脚本创建全局extension1extension2窗口中的变量。显然,全球范围引起了一些问题。

I think I solved the problem:

var points = [];

function makeCube(d, point) {
  console.log(d, JSON.stringify(point));
  
  if(d == 0) {
    points.push([...point]);
  } else {
    let extension1 = [...point];
    extension1.push(0);

    let extension2 = [...point];
    extension2.push(1);
    
    makeCube(d - 1, extension1);
    makeCube(d - 1, extension2);
  }
}

makeCube(3, [])

3 []
2 [0]
1 [0,0]
0 [0,0,0]
0 [0,0,1]
1 [0,1]
0 [0,1,0]
0 [0,1,1]
2 [1]
1 [1,0]
0 [1,0,0]
0 [1,0,1]
1 [1,1]
0 [1,1,0]
0 [1,1,1]

I just added let twice (and changed what I logged).
The original script creates global extension1 and extension2 variables in the window. Apparently, the global scope caused some problems.

荒岛晴空 2025-01-28 11:21:32

您可以使用发电机在功能之外移动副作用,console.log。这也使跳过全局变量变得容易。使用for..of循环遍历所有点 -

function* makeCube(d, point = []) {
  yield point
  if(d == 0) return
  yield *makeCube(d - 1, [...point, 0])
  yield *makeCube(d - 1, [...point, 1])
}

for (const point of makeCube(3))
  console.log(`(${point.join(",")})`) // caller decides effect

()
(0)
(0,0)
(0,0,0)
(0,0,1)
(0,1)
(0,1,0)
(0,1,1)
(1)
(1,0)
(1,0,0)
(1,0,1)
(1,1)
(1,1,0)
(1,1,1)

或使用array.from

const points = Array.from(makeCube(3))

console.log(points)
[
  [],
  [0],
  [0,0],
  [0,0,0],
  [0,0,1],
  [0,1],
  [0,1,0],
  [0,1,1],
  [1],
  [1,0],
  [1,0,0],
  [1,0,1],
  [1,1],
  [1,1,0],
  [1,1,1],
]

如果要计算product,我建议您以不同的方式编写该功能 -

function* product(t, ...more) {
  if (t == null) return yield []
  for (const p of product(...more))
    for (const v of t)
      yield [v, ...p]
}

for (const p of product([0,1], [0,1], [0,1]))
  console.log(p.join(","))
  
for (const p of product(["J", "Q", "K", "A"], ['♡', '♢', '♤', '♧']))
  console.log(p.join(""))
  

0,0,0
1,0,0
0,1,0
1,1,0
0,0,1
1,0,1
0,1,1
1,1,1
J♡
Q♡
K♡
A♡
J♢
Q♢
K♢
A♢
J♤
Q♤
K♤
A♤
J♧
Q♧
K♧
A♧

You can use a generator to move the side effect, console.log, outside of the function. This also makes it easy to skip the global points variable. Use a for..of loop to iterate through all the points -

function* makeCube(d, point = []) {
  yield point
  if(d == 0) return
  yield *makeCube(d - 1, [...point, 0])
  yield *makeCube(d - 1, [...point, 1])
}

for (const point of makeCube(3))
  console.log(`(${point.join(",")})`) // caller decides effect

()
(0)
(0,0)
(0,0,0)
(0,0,1)
(0,1)
(0,1,0)
(0,1,1)
(1)
(1,0)
(1,0,0)
(1,0,1)
(1,1)
(1,1,0)
(1,1,1)

Or use Array.from to collect all of the points into an array

const points = Array.from(makeCube(3))

console.log(points)
[
  [],
  [0],
  [0,0],
  [0,0,0],
  [0,0,1],
  [0,1],
  [0,1,0],
  [0,1,1],
  [1],
  [1,0],
  [1,0,0],
  [1,0,1],
  [1,1],
  [1,1,0],
  [1,1,1],
]

If you want to compute the product, I would suggest you write the function somewhat differently -

function* product(t, ...more) {
  if (t == null) return yield []
  for (const p of product(...more))
    for (const v of t)
      yield [v, ...p]
}

for (const p of product([0,1], [0,1], [0,1]))
  console.log(p.join(","))
  
for (const p of product(["J", "Q", "K", "A"], ['♡', '♢', '♤', '♧']))
  console.log(p.join(""))
  

0,0,0
1,0,0
0,1,0
1,1,0
0,0,1
1,0,1
0,1,1
1,1,1
J♡
Q♡
K♡
A♡
J♢
Q♢
K♢
A♢
J♤
Q♤
K♤
A♤
J♧
Q♧
K♧
A♧
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文