【问题标题】:Javascript - Loop through array backwards with forEachJavascript - 使用 forEach 向后循环数组
【发布时间】:2015-09-20 18:44:34
【问题描述】:

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

【问题讨论】:

  • 您到底想做什么?按照措辞,这是一个 XY 问题,询问未知问题的特定潜在解决方案。
  • 可能的用例是,如果有人在维护图像编辑器的“层”,它们都可能是数组的一部分,并且前后循环遍历它们可能是至关重要的。

标签: javascript arrays


【解决方案1】:

let arr = [1, 2, 3];

arr.slice().reverse().forEach(x => console.log(x))

将打印:

3
2
1

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

【讨论】:

  • 与仅使用 for 循环并向后迭代相比,这非常低效。如果 OP 真的需要一个函数,他们可以在内部使用 for 循环的数组原型上添加一个 forEachReverse 函数。
  • @kennsorr OP 询问“没有实际反转数组本身”,并且 .reverse() 修改了调用它的数组实例。 .slice() 是一种快速创建数组新副本的方法。
【解决方案2】:

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

const array = ['alpha', 'beta', 'gamma'];

array.reduceRight((_, elem) => console.log(elem), null);

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

如果可以选择包含库:

Lodash:forEachRight

【讨论】:

  • 唯一不可怕或不明显的答案。好一个。不过,我可能仍然不会在简单的反向 for 循环中使用它——阅读起来太混乱了。
  • 很棒的答案。与大多数其他解决方案相比,它不会就地操作它所操作的数组!
【解决方案3】:

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

我可以想到两个选项,它们仅使用 precursors 来使用 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));

【讨论】:

  • 您的密钥反转方法比仅对集合本身进行反转更好吗?
  • @victor175:OP 说他不想反转数组(“......没有实际反转数组本身”)。
  • @T.J.Crowder ...using slice().reverse() like this answer 实际上并没有反转数组。
  • @ashleedawg- 恐怕我不明白你的评论。我没有说slice().reverse() 颠倒了原来的——事实上,我上面说的正好相反——见第一个代码sn-p。所以...?
  • 有了这个答案,你得到的是原始索引而不是反向索引,所以它更有用
【解决方案4】:

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

const array = ['blastoff', 1, 2, 3];

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

【讨论】:

  • 哦...在阅读其他答案后,我对开发人员失去了信心,但这是正确有效的解决方案
  • 引用问题:“不是任何其他类型的循环,我知道如何使用 for / 标准方式”,这个答案是不合适的。
  • @Guntram 这是最快的方法。我能想到的不为此目的使用 for 循环的唯一原因是,提出这个问题的人试图在他们的 CS 作业上作弊。 :D
  • 我认为提问者正在寻找他们希望存在的某种标准forEachReverse()。他们问题的真正答案是“对不起,它不存在”。
【解决方案5】:

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

所以你可以创建自己的Array.revEach 并让它优于原生Array.forEach,我想我希望浏览器能尽快解决Array.forEach 的性能非常慢的问题,并且不需要polyfill 实际现有的方法。

对于Array.revEach,在“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
    }
  };
}

【讨论】:

    【解决方案6】:

    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
    

    【讨论】:

    • 这只是做一个普通的for循环的一种非常复杂的方式。
    【解决方案7】:

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

    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
    

    【讨论】:

    • 其实.reverse()会反转someArray,所以你需要再做一次someArray.reverse(),否则会导致不受欢迎的bug。
    • @V.Dalechyn 两个reverse()s 不对!这是一个糟糕的答案。
    • @Timmmm 已经快两年了,感谢您的回复:D
    【解决方案8】:

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

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

    【讨论】:

    • array[array.length] 未定义,所以您可能的意思是“让 start = array.length - 1”
    【解决方案9】:

    你也可以这样做

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

    【讨论】:

      猜你喜欢
      • 2021-12-10
      • 2017-03-17
      • 2021-10-19
      • 2015-10-31
      • 2015-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      相关资源
      最近更新 更多