在JavaScript中反转一个数组而不改变原始数组

363

Array.prototype.reverse 可以在原地(通过变异)反转数组的内容...

是否有一种类似简单的策略可以在不改变原始数组内容的情况下反转数组(无变异)?


这里有一个比较不同选项的基准测试:http://jsben.ch/HZ7Zp - Solomon Ucko
16个回答

1

跳进2022年,这里是今天最高效的解决方案(性能最佳,且不需要额外的内存使用)。


对于任何ArrayLike类型,最快速地反转它的方法是逻辑上的,将其包装成一个反转的可迭代对象:

function reverse<T>(input: ArrayLike<T>): Iterable<T> {
    return {
        [Symbol.iterator](): Iterator<T> {
            let i = input.length;
            return {
                next(): IteratorResult<T> {
                    return i
                        ? {value: input[--i], done: false}
                        : {value: undefined, done: true};
                },
            };
        },
    };
}

通过这种方式,您可以反向迭代任何 ArraystringBuffer,而无需进行任何额外的复制或处理来获取反向数据:

for(const a of reverse([1, 2, 3])) {
    console.log(a); //=> 3 2 1
}

这是最快的方法,因为您不需要复制数据,也不需要进行任何处理,只需逻辑上反转即可。


1

为了演示目的而进行原地反转,使用变量交换(但如果您不想改变原始数据,就需要创建一个副本)

const myArr = ["a", "b", "c", "d"];
const copy = [...myArr];
for (let i = 0; i < (copy.length - 1) / 2; i++) {  
    const lastIndex = copy.length - 1 - i; 
    [copy[i], copy[lastIndex]] = [copy[lastIndex], copy[i]] 
}


0

有没有类似简单的策略可以在不改变原始数组内容(无突变)的情况下反转数组?

是的,可以通过使用返回应用操作后的新集合的to[Operation]方法来实现这一点(目前处于第三阶段,即将推出)。

实现方式如下

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

const reversedArr = arr.toReverse();

console.log(arr); // [5, 4, 3, 2, 1]

console.log(reversedArr); // [1, 2, 3, 4, 5]

未捕获的类型错误: arr.toReverse 不是一个函数。在JavaScript中没有toReverse。 - Cerbrus
1
@Cerbrus 目前还没有实现 - 它仍然是一个提案,处于最后阶段之前。可以使用Polyfills来预览功能:例如在这里 - VLAZ

0
不是最好的解决方案,但它能起作用。

Array.prototype.myNonMutableReverse = function () {
  const reversedArr = [];
  for (let i = this.length - 1; i >= 0; i--) reversedArr.push(this[i]);
  return reversedArr;
};

const a = [1, 2, 3, 4, 5, 6, 7, 8];
const b = a.myNonMutableReverse();
console.log("a",a);
console.log("////////")
console.log("b",b);


-1

转换为普通JavaScript:

function reverseArray(arr, num) {
  var newArray = [];
  for (let i = num; i <= arr.length - 1; i++) {
    newArray.push(arr[i]);
  }

  return newArray;
}

-9

ES6:

const reverseArr = [1,2,3,4].sort(()=>1)

5
欢迎来到SO,Radion!在回答问题时,通常最好解释一下为什么你的答案有效以及你是如何得出这个结论的,这可以帮助新用户理解你所指定的交互和语言。 - Ethan Field
在Radion的辩护中 :P 因为这就是Array.prototype.sort回调函数(或所谓的“比较函数”)的工作方式,所以末尾的1可以是任何大于零的数字。基本上,您始终比较2个数字,在这种情况下,比较始终返回正数,因此它总是说将第二个数字移动到第一个数字前面 :) 这非常详细说明了: https://dev59.com/Cmw15IYBdhLWcg3wfsBy - iulial
9
sort() 改变数组本身(即就地排序),这正是原帖作者想要避免的。 - clint
8
这个答案有几个错误。 (1) 正如@ClintHarris所指出的那样,它改变了数组,因此与.reverse()没有什么区别。 (2) 您的比较器是非法的--当您为a,b返回1时,您必须为b,a返回负数。如果您的答案在某些实现中翻转了数组,这完全是运气所致。 - Don Hatch
请在提交代码时进行测试。至少它应该完成所需的任务,即使它会改变数组。这个代码并没有按照预期工作(它根本没有改变数组)(演示),只需要添加一个字符就可以轻松修正。 - General Grievance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接