简体   繁体   English

Javascript 中的反向数组而不改变原始数组

[英]Reverse array in Javascript without mutating original array

Array.prototype.reverse reverses the contents of an array in place (with mutation)... Array.prototype.reverse原地反转数组的内容(带有突变)...

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation)?是否有类似的简单策略来反转数组而不改变原始数组的内容(无突变)?

You can use slice() to make a copy then reverse() it您可以使用slice()进行复制,然后使用reverse()

var newarray = array.slice().reverse();

 var array = ['a', 'b', 'c', 'd', 'e']; var newarray = array.slice().reverse(); console.log('a', array); console.log('na', newarray);

在 ES6 中:

const newArray = [...array].reverse()

Another ES6 variant:另一个 ES6 变体:

We can also use .reduceRight() to create a reversed array without actually reversing it.我们还可以使用.reduceRight()创建一个反转数组,而无需实际反转它。

 let A = ['a', 'b', 'c', 'd', 'e', 'f']; let B = A.reduceRight((a, c) => (a.push(c), a), []); console.log(B);

Useful Resources:有用的资源:

Try this recursive solution:试试这个递归解决方案:

const reverse = ([head, ...tail]) => 
    tail.length === 0
        ? [head]                       // Base case -- cannot reverse a single element.
        : [...reverse(tail), head]     // Recursive case

reverse([1]);               // [1]
reverse([1,2,3]);           // [3,2,1]
reverse('hello').join('');  // 'olleh' -- Strings too!                              

An ES6 alternative using .reduce() and spreading.使用.reduce()和传播的 ES6 替代方案。

const foo = [1, 2, 3, 4];
const bar = foo.reduce((acc, b) => ([b, ...acc]), []);

Basically what it does is create a new array with the next element in foo, and spreading the accumulated array for each iteration after b.基本上它所做的就是用 foo 中的下一个元素创建一个新数组,并在 b 之后为每次迭代传播累积的数组。

[]
[1] => [1]
[2, ...[1]] => [2, 1]
[3, ...[2, 1]] => [3, 2, 1]
[4, ...[3, 2, 1]] => [4, 3, 2, 1]

Alternatively .reduceRight() as mentioned above here, but without the .push() mutation.或者.reduceRight()如上所述,但没有.push()突变。

const baz = foo.reduceRight((acc, b) => ([...acc, b]), []);

There are multiple ways of reversing an array without modifying.有多种方法可以在不修改的情况下反转数组。 Two of them are其中两个是

var array = [1,2,3,4,5,6,7,8,9,10];

// Using Splice
var reverseArray1 = array.splice().reverse(); // Fastest

// Using spread operator
var reverseArray2 = [...array].reverse();

// Using for loop 
var reverseArray3 = []; 
for(var i = array.length-1; i>=0; i--) {
  reverseArray.push(array[i]);
}

Performance test http://jsben.ch/guftu性能测试http://jsben.ch/guftu

const newArr = Array.from(originalArray).reverse();

const arrayCopy = Object.assign([], array).reverse()

This solution:这个解决方案:

-Successfully copies the array - 成功复制数组

-Doesn't mutate the original array - 不改变原始数组

-Looks like it's doing what it is doing - 看起来它正在做它正在做的事情

Reversing in place with variable swap just for demonstrative purposes (but you need a copy if you don't want to mutate)仅出于演示目的使用变量交换就地反转(但如果您不想变异,则需要一个副本)

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]] 
}

While array.slice().reverse() is what I would myself go for in a situation where I cannot use a library, it's not so good in terms of readability: we are using imperative logic that the person reading the code must think through.虽然array.slice().reverse()是我自己在无法使用库的情况下使用的,但它在可读性方面并不是那么好:我们使用的是命令式逻辑,阅读代码的人必须仔细考虑. Considering also that there is the same problem with sort , there's a solid justification here for using a utility library.还考虑到sort也存在同样的问题,这里有充分的理由使用实用程序库。

You can use a function pipe from fp-ts or a library I've written myself .您可以使用来自fp-ts的函数pipe我自己编写的库 It pipes a value though a number of functions, so pipe(x, a, b) is equivalent to b(a(x)) .它通过多个函数传递一个值,因此pipe(x, a, b)等价于b(a(x)) With this function, you can write使用此函数,您可以编写

pipe(yourArray, reverseArray)

where reverseArray is a function that basically does .slice().reverse() , ie reverses the array immutably.其中reverseArray是一个基本上执行.slice().reverse()的函数,即不可变地反转数组。 Generally speaking, pipe lets you do the equivalent of dot-chaining, but without being limited to the methods available on the array prototype.一般来说, pipe可以让你做点链接的等价物,但不限于数组原型上可用的方法。

There's a new tc39 proposal , which adds a toReversed method to Array that returns a copy of the array and doesn't modify the original.有一个新的tc39 提案,它向Array添加了一个toReversed方法,该方法返回数组的副本并且不修改原始数组。

Example from the proposal:提案示例:

const sequence = [1, 2, 3];
sequence.toReversed(); // => [3, 2, 1]
sequence; // => [1, 2, 3]

As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js .由于它目前处于第 3 阶段,它可能很快就会在浏览器引擎中实现,但与此同时,这里core-js中提供了一个 polyfill。

Is there a similarly simple strategy for reversing an array without altering the contents of the original array (without mutation) ?是否有类似简单的策略来反转数组而不改变原始数组的内容(没有突变)?

Yes, there is a way to achieve this by using to[Operation] that return a new collection with the operation applied (This is currently at stage 3, will be available soon).是的,有一种方法可以通过使用to[Operation]返回一个应用了操作的新集合来实现这一点(目前处于第 3 阶段,即将推出)。

Implementation will be like :实施将如下所示

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]

Jumping into 2022, and here's the most efficient solution today (highest-performing, and no extra memory usage).进入 2022 年,这是当今最高效的解决方案(性能最高,并且没有额外的内存使用)。


For any ArrayLike type, the fastest way to reverse is logically, by wrapping it into a reversed iterable:对于任何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};
                },
            };
        },
    };
}

This way you can reverse-iterate through any Array , string or Buffer , without any extra copy or processing for the reversed data:通过这种方式,您可以反向迭代任何ArraystringBuffer ,而无需对反向数据进行任何额外的复制或处理:

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

It is the fastest approach, because you do not copy the data, and do no processing at all, you just reverse it logically.这是最快的方法,因为你不复制数据,根本不做任何处理,你只是逻辑反转。

Not the best solution but it works不是最好的解决方案,但它有效

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

INTO plain Javascript: INTO纯Javascript:

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

  return newArray;
}

Here are some cool ways to reverse an array 这里有一些很酷的方法来反转数组

es6:

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

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

相关问题 过滤javascript树而不更改原始数组 - Filter a javascript tree without mutating the original array 如何在不更改原始数组的情况下过滤嵌套数组? - How can I filter a nested array without mutating the original array? 在不改变原始数组的情况下在数组中添加对象的算法 - algorithm to add up objects in an array without mutating the original array 如何在不改变原始数组的情况下对数组进行排序? - How can you sort an array without mutating the original array? 如何将数组传递给函数而不改变原始数组? - How to pass an array to a function without mutating the original array? 如何在对象的嵌套数组中添加对象而不改变原始源 - how to add object in nested array of objects without mutating original source 如何在不更改原始数组的情况下破坏对象属性? - How do i destruct object properties without mutating original array? 如何在不更改原始数组的情况下更改对象Key - How to change an object Key without mutating original array 避免更改JavaScript数组 - Avoid Mutating JavaScript array 当模板与原始数组绑定时,搜索功能不会改变原始数组? - Search functionality without mutating the Original array when template is binded with Original array?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM