web-dev-qa-db-ja.com

Javascript / angular-forEachで配列を逆方向にループする

forEachを使用して配列を逆方向にループする方法はありますか?

16
Mankind1023
_var arr = [1, 2, 3];

arr.slice().reverse().forEach(function(x) {
    console.log(x);
})
_

印刷されます:

_3
2
1
_

arrは引き続き_[1, 2, 3]_のままで、.slice()は浅いコピーを作成します。

31
naartjie

いいえ、forEachは配列を順方向に処理するだけです。だから、あなたはあなたの質問であなたが言った範囲外であると言った他の何かをしなければならないだろう。

forEachの使用にprecursorsを使用する(したがって、forループまたは他の種類のループを使用しない)2つのオプションを考えることができます。それらが範囲外かどうかはわかりませんので、ここにあります:

  1. 配列をコピーし、コピーを逆にして、forEachを使用します

  2. 使用する Object.keysインデックスを取得し、それを逆にして、その上でforEachを使用します(値ではなくインデックスをループしますが、それからルックアップできます)。

#1です。

sliceは配列をコピーします(浅いコピーなので、高価ではない可能性が高い)。次に、それを逆にした後、forEachを使用します。

var a = ['one', 'two', 'three'];
a.slice().reverse().forEach(function(entry) {
    snippet.log(entry);
});
snippet.log("Proof that a is not, itself, reversed: " +
            JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

#2は次のとおりです。

を使用しております Object.keys(配列に要素以外のプロパティを格納する場合はfilterを使用して)配列インデックスを取得し、thatを逆にして、結果をループします。

var a = ['one', 'two', 'three'];
Object.keys(a).reverse().forEach(function(index) {
    snippet.log(a[index]);
});
snippet.log("Proof that a is not, itself, reversed: " +
            JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

補足:配列に要素以外のプロパティがある場合にfilterを使用することの意味は次のとおりです。

var a = ['one', 'two', 'three'];
a.nonElementProperty = "foo";
Object.keys(a).filter(function(name) {
  return String(+name) === name;
}).reverse().forEach(function(index) {
    snippet.log(a[index]);
});
snippet.log("Proof that a is not, itself, reversed: " +
            JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
9
T.J. Crowder

これは 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
5
John

Forループを使用してください。配列の最後から始めて、そこから逆方向に進みます。

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

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

hasの逆カウンター部分を持つ同様の配列メソッドがあり、reducereduceRightと一緒になります

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

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

要求された目的に使用する場合は、必ず2番目の引数を指定してください。 nullまたはその他のいずれかです。また、コールバック関数は最初の引数としてアキュムレータを持っていることに注意してください。これはこの目的には必要ありません。

ライブラリを含めることがオプションの場合:

Lodash: forEachRight

3
trincot

まだブラウザーは_Array.forEach_関数を最適化していないようです。それほど労力をかけることなく、_Array.forEach_メソッドを少なくとも10対1実行する単純なポリフィルを作成できます。

したがって、独自の_Array.revEach_を作成し、ネイティブ_Array.forEach_を上回ることができます。ブラウザが_Array.forEach_の非常に遅いパフォーマンスに対処し、実際の既存のメソッドをポリフィルする必要があることを願っています必要はありません。

_Array.revEach_の場合、「Chrome 46.0.2490.22 beta-m」で17倍速く実行される_Array.forEach_を実行します

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

リバースに変更された実際の公式ポリフィルを追加するだけです。コメントは私の変更を示しています。

_// 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
    }
  };
}
_
2
Blindman67

array.forEachには3つのパラメーターがあります。これらを使用して、それぞれを効果的に後方に移動できます。

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
1
grabbag