繁体   English   中英

Javascript - 使用 forEach 向后循环数组

[英]Javascript - Loop through array backwards with forEach

有没有办法使用forEach向后循环数组(不是任何其他类型的循环,我知道如何使用 for / 标准方式)并且实际上不反转数组本身?

 let arr = [1, 2, 3]; arr.slice().reverse().forEach(x => console.log(x))

将打印:

3
2
1

arr仍然是[1, 2, 3].slice()创建一个浅拷贝。

有一个类似的数组方法,它一个反向计数器部分, reducereduceRight一起出现:

 const array = ['alpha', 'beta', 'gamma']; array.reduceRight((_, elem) => console.log(elem), null);

将其用于请求的目的时,请确保提供第二个参数。 它可以为null或其他任何值。 另请注意,回调函数将累加器作为第一个参数,为此您不需要它。

如果包括一个库是一个选项:

罗达什: forEachRight

只需使用 for 循环。 从数组的末尾开始,然后从那里倒退。

 const array = ['blastoff', 1, 2, 3]; for (let index = array.length - 1; index >= 0; index--) { const element = array[index]; console.log(element); }

不, forEach仅通过数组向前处理。 所以你必须做其他事情,你在问题中所说的超出了范围。

我可以想到两个选项,它们只使用使用forEach前体(因此,它们不使用for循环或其他类型的循环)。 我不知道这些是否超出范围,所以这里是:

  1. 复制数组并反转副本,然后在其上使用forEach

  2. 使用Object.keys获取索引,将其反转,然后在其上使用forEach (它将遍历索引,而不是值,但我们可以查找它们)

这是#1:

slice复制数组(浅复制,因此不太可能很昂贵),然后我们将其反转,然后forEach

 var a = ['one', 'two', 'three']; a.slice().reverse().forEach(function(entry) { console.log(entry); }); console.log("Proof that a is not, itself, reversed: " + JSON.stringify(a));

这是#2:

我们使用Object.keys获取数组索引(如果您在数组中存储非元素属性,则使用filter ),反转,然后遍历结果:

 var a = ['one', 'two', 'three']; Object.keys(a).reverse().forEach(function(index) { console.log(a[index]); }); console.log("Proof that a is not, itself, reversed: " + JSON.stringify(a));


旁注:如果您的数组上有非元素属性,这就是我使用filter的意思:

 var a = ['one', 'two', 'three']; a.nonElementProperty = "foo"; Object.keys(a).filter(function(name) { return String(+name) === name; }).reverse().forEach(function(index) { console.log(a[index]); }); console.log("Proof that a is not, itself, reversed: " + JSON.stringify(a));

到目前为止,浏览器似乎还没有优化Array.forEach函数。 不费吹灰之力,您就可以编写一个简单的 polyfill,以至少 10 比 1 的比例执行Array.forEach方法。

因此,您可以创建自己的Array.revEach并使其性能优于原生Array.forEach ,我希望浏览器能够尽快解决Array.forEach性能非常缓慢的问题,并且不需要 polyfill 实际存在的方法。

For Array.revEach out 在“Chrome 46.0.2490.22 beta-m”上执行Array.forEach运行速度快 17 倍

if (Array.prototype.revEach === undefined) { 
    Object.defineProperty(Array.prototype, 'revEach', { 
        writable : false,
        enumerable : false,
        configurable : false,
        value : function (func) {
            var i;
            var len = this.length-1;
            for (i = len; i >= 0; i--) {
                func(this[i], i, this);
            }
        }
    });
}

只是添加实际的官方polyfill修改为reverse。 评论显示我的更改。

// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
// Modified by Blindman67 to revEach
if (!Array.prototype.revEach) {   // name changed
  Array.prototype.revEach = function(callback, thisArg) { // name changed
    var T;  // k defined where len was
    if (this == null) {
      throw new TypeError(' this is null or not defined');
    }
    var O = Object(this);
    var k = (O.length >>> 0)-1;  // set k (counter) ToUint32
                                 // len var removed
    if (typeof callback !== "function") {
      throw new TypeError(callback + ' is not a function');
    }
    if (arguments.length > 1) {
      T = thisArg;
    }
    while (k >= 0) {  // reverse condition
      var kValue;
      if (k in O) {
        kValue = O[k];
        callback.call(T, kValue, k, O);
      }
      k--;  // dec counter
    }
  };
}

array.forEach 有 3 个参数。 您可以使用这些来有效地向后 forEach。

var arr = [1, 2, 3];

    arr.forEach(function(x, index, the_array) {
        let x_prime = the_array[the_array.length-1-index]
        console.log(x_prime);
    })

将打印

3
2
1

这可以使用reverse方法、 forEach方法和(如果使用 ES6) 箭头函数相对简洁地完成

var someArray = ["a","b","c","d"];
someArray.reverse().forEach(arrayItem =>
    console.log(arrayItem)
)

如果你不使用 ES6,解决方案大致相同,只是没有箭头功能。

var someArray = ["a","b","c","d"];
someArray.reverse().forEach(function(arrayItem) {
    console.log(arrayItem)
})

两者都将打印到控制台:

d
c    
b
a

有很多方法可以完成这项任务。

  1. 首先我们可以使用 Array.reduceRight() 方法

 [1,2,3,4,5].reduceRight((total,item) => { console.log(item); // Do somthing here and remember the return statement return item; },0) Output: 5,4,3,2,1

reduceRight 方法以从右到左的方式遍历数组,我们可以利用它。

,但请始终记住,您必须返回一些东西才能继续循环,直到达到长度。

  1. 作为第二种方法,我们可以使用Array.reverse()

该方法首先以相反的方式格式化数组然后返回它,现在您可以以相反的方式迭代。

[1,2,3].reverse().map(n => console.log(n));
Output: 3,2,1

但是这种方法的缺点是,如果数组中有数千个条目,那么它可能会影响您的性能。

  1. 第三种也是最简单的使用经典 for 循环的方法

 let array = [1,2,3,4,5]; let start = array.length; for(;start >= 0;start--){ // travese in right to left manner console.log(array[start]) }

关于什么:

const array = [1, 2, 3];
const revArray = [...array].reverse() // won't affect the original array
revArray.forEach(x => console.log(x)) // 3, 2, 1

一个班轮:

[...array].reverse().forEach(x => console.log(x)) // 3, 2, 1

使用索引变量:

[...array].reverse().forEach((val, index) => {
  const revIndex = array.length - i - 1
  console.log(revIndex) // 0, 1, 2
  console.log(revIndex) // 2, 1, 0
  console.log(val) // 3, 2, 1
})

你也可以这样做

let arr = [1, 3, 5, 7, 9];

arr.forEach(value => {
    console.log(value);
})

let reversed = new Array(arr.reverse());
console.log("\n\nReversed: ");

reversed.forEach(value => {
    value.forEach(val => {
        console.log(val)
    })
})

暂无
暂无

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

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