web-dev-qa-db-ja.com

JavaScriptでマップを反復処理する

私はこのような構造を持っています:

var myMap = {
    partnr1: ['modelA', 'modelB', 'modelC'],
    partnr2: ['modelA', 'modelB', 'modelC']
};

各関連要素(partnr)を関連要素(モデル)で繰り返し処理します。

これを達成するために、$ eachを2回繰り返してみましたが、何も起こりません。

$.each(myMap, function (i, val) {
    $.each(i, function (innerKey, innerValue) {

        setTimeout(function () {
            $('#variant').fadeOut("slow", function () {
                $(this).text(innerKey + "-" + innerValue).fadeIn("slow");

            });

        }, i * 6000);

    });
});

私が達成しようとしているフェードインとフェードアウトの効果は、単一の値配列(オブジェクト)を使用する場合は正常に機能しますが、ここのように各キーに複数の値が必要な場合は機能しません。

この反復を成功させる方法についてのアイデアはありますか?この場合にはマップを使用する以外の方法がありますか?

どんな提案も興味があるでしょう。

18
user2374903

私は標準のjavascriptを使用します:

for (var m in myMap){
    for (var i=0;i<myMap[m].length;i++){
    ... do something with myMap[m][i] ...
    }
} 

オブジェクトと配列を処理するさまざまな方法に注意してください。

29
Atle

2019年の質問に対する回答:

使用するECMAScriptのバージョンによって異なります。

ES6以前:

上記の回答のいずれかを使用します。例:

_for (var m in myMap){
    for (var i=0;i<myMap[m].length;i++){
    ... do something with myMap[m][i] ...
    }
} 
_

ES6の場合(ES 2015):

Mapオブジェクトを使用する必要があります。このオブジェクトには、entries()関数があります。

_var myMap = new Map();
myMap.set("0", "foo");
myMap.set(1, "bar");
myMap.set({}, "baz");

for (const [key, value] of myMap.entries()) {
  console.log(key, value);
}
_

ES8の場合(ES 2017):

Object.entries() が導入されました:

_const object = {'a': 1, 'b': 2, 'c' : 3};
for (const [key, value] of Object.entries(object)) {
  console.log(key, value);
}
_
7
David Nathan

$.each()へのコールバックには、プロパティ名と値がこの順序で渡されます。したがって、$.each()の内部呼び出しでプロパティ名を反復処理しようとしています。あなたが欲しいと思う:

$.each(myMap, function (i, val) {
  $.each(val, function(innerKey, innerValue) {
    // ...
  });
});

内側のループでは、マップのようなオブジェクトを指定すると、値は配列になります。それで構いませんが、「innerKey」の値はすべて数字になります。

編集 —これが解決したら、次の問題があります。

    setTimeout(function () {

      // ...

    }, i * 6000);

そのループを最初に通過するとき、「i」はストリング「partnr1」になります。したがって、その乗算の試行はNaNになります。外部マップのプロパティカウントを追跡する外部カウンターを保持できます。

var pcount = 1;
$.each(myMap, function(i, val) {
  $.each(val, function(innerKey, innerValue) {
    setTimeout(function() {
      // ...
    }, pcount++ * 6000);
  });
});
3
Pointy

これを行うためにイテレータを使用しないでください。コールバックのカウンターをインクリメントし、次のアイテムの操作を再帰的に呼び出すことにより、独自のループを維持します。

$.each(myMap, function(_, arr) {
    processArray(arr, 0);
});

function processArray(arr, i) {
    if (i >= arr.length) return;

    setTimeout(function () {
        $('#variant').fadeOut("slow", function () {
            $(this).text(i + "-" + arr[i]).fadeIn("slow");

            // Handle next iteration
            processArray(arr, ++i);
        });
    }, 6000);
}

コードに論理エラーがありますが。同じコンテナを(おおよそ)同時に複数の異なる値に設定しています。おそらく、それぞれが独自のコンテナを更新することを意味します。

1
user1106925