array.reverse() 在平面数组中逐块

array.reverse() block-wise in flat array

我正在编写一个像素动画,从 Unit8Array 中读取数据 5 帧,每帧 72 个二进制文件。现在我想反转帧来反转动画。所以我的问题:

有没有办法按块反转,或者有谁有创意,我该怎么做? (我不能只是 运行 向后,因为每一帧都需要前一帧的信息)

const myArr = [1,2,3,4,5,6,7,8];
console.log(myArr.reverse());//8,7,6,5,4,3,2,1 
//how to reach [7,8,5,6,3,4,1,2]?

//would work fine with 2D array,
//but don't have 2D
const my2D = [[1,2],[3,4],[5,6],[7,8]];

应该这样做:

const reversed = myArr
  .map((_, i, a) => a[i ^ 1])
  .reverse()

它的工作方式是将每个数组元素映射到另一个元素,并通过使用 XOR 反转 1 位来更改索引(例如 4^1=5、5^1=4、6^1=7 , 7^1=6, 等等) 然后反转整个数组.

此技巧可用于任何 2 的幂:您可以使用 ^ 3 翻转 1 位和 2 位反转 4 个元素组,使用 ^ 7 翻转 4 位反转 8 个元素组, 2 和 1 位等等。 (如果您需要其他组大小,则必须使用更昂贵的操作,例如 i + size - 1 - 2 * (i % size)。)

map 使用几个参数调用回调 - 第一个是元素的值,但我们真的不需要它,所以我们将它分配给一个未使用的变量 _ .第二个是索引,第三个是数组本身。实际上我们只需要索引,但是使用第三个参数我们可以避免在行中写两次数组的名称(myArr.map((_, i) => myArr[i ^ 1]) 也可以)。

注意:根据您的确切用例,另一种选择可能是在 访问 数据时对索引执行 array.length - i ^ 1 操作,而不是创建新的索引数组。

受 CherryDT 的回答启发,一次 map 调用即可完成:

const arr = [1,2,3,4,5,6,7,8];

console.log(
  arr.map((_, i) => arr[arr.length - i - 1 ^ 1])
);