【问题标题】:iterate through a map in javascript遍历javascript中的地图
【发布时间】:2013-05-06 15:35:24
【问题描述】:

我有这样的结构:

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

我将遍历每个元素(partnr)及其关联对象(模型)。

我正在尝试两次 $each 迭代以实现此目的,但没有任何反应:

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

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

            });

        }, i * 6000);

    });
});

我试图实现的淡入淡出效果在使用单个值数组(对象)时工作正常,但当我需要像这里这样的每个键有多个值时就不行了。

关于如何成功完成此迭代的任何想法以及在这种情况下使用地图之外的其他方法吗?

任何建议都会很有趣。

【问题讨论】:

  • 这不是Map,而是Object

标签: javascript jquery map


【解决方案1】:

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

Map.prototype.entries() 介绍:

const mapOne = new Map([['a', 1], ['b', 2], ['c' , 3]]);
for (const [key, value] of mapOne.entries()) {
  console.log(key, value);
}

【讨论】:

  • 我想问一个愚蠢的问题,当最终用户可能使用旧版浏览器时,为什么还要使用 ES8?
  • @Erik:JS 开发也发生在 Web 开发以外的领域。在那里,您可能不必担心旧的浏览器版本,并且可以享受 ES8 带来的改进。
  • @Erik 转译器(如 babel)帮助将新版本的 js 转换为旧版本的 js。所以即使用户使用的是旧版浏览器,我们转译后的 ES8 代码仍然可以在旧版浏览器上运行。
【解决方案2】:

嗯,看起来这个旧的 JQuery 线程已被 ES6 Map 用户使用。

如果这是您要查找的内容,我建议您使用Array.from() 函数将Map 转换为Array。这使您可以轻松链接转换,例如filter()map() 等。

const map = new Map([
  ['key one', 'value one'],
  ['key two', 'value two'],
]);

// Loop through key-value-pairs
Array.from(map.entries()).map(([key, val]) => console.log(key, val));

// Loop through map keys
Array.from(map.keys()).map(key => console.log(key));

// Loop through values
Array.from(map.values()).map(value => console.log(value));

【讨论】:

    【解决方案3】:

    ES6+ 的函数式方法

    如果您想采用更实用的方法来迭代 Map 对象,您可以这样做

    const myMap = new Map() 
    myMap.forEach((value, key) => {
        console.log(value, key)
    })
    

    【讨论】:

      【解决方案4】:

      $.each() 的回调按顺序传递属性名称和值。因此,您试图在对$.each() 的内部调用中迭代属性名称。我想你想要:

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

      在内部循环中,给定一个像地图这样的对象,值是数组。没关系,但请注意“innerKey”值都是数字。

      edit — 现在一旦理顺了,下一个问题就来了:

          setTimeout(function () {
      
            // ...
      
          }, i * 6000);
      

      第一次通过该循环时,“i”将是字符串“partnr1”。因此,该乘法尝试将导致NaN。您可以保留一个外部计数器来跟踪外部地图的属性计数:

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

      【讨论】:

      • 感谢您的回复。通过将 $.each(i... 更改为 $.each(val..最终迭代。
      • @user2374903 不,它没有跳到最后一个,尽管它似乎正在这样做。我没有仔细查看“setTimeout”调用,所以我将添加到我的答案中。
      • 通过将 pcount 从 1 更改为 0(这意味着它从第一个循环开始),代码可以工作,但只是一个一个地显示模型。我没有说清楚的错误,目标是让与该partnumer相对应的所有模型显示为淡入列表。
      【解决方案5】:

      不要使用迭代器来执行此操作。通过在回调中增加一个计数器来维护您自己的循环,并递归地调用下一项的操作。

      $.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);
      }
      

      虽然您的代码中存在逻辑错误。您在(大致)同时将同一个容器设置为多个不同的值。也许您的意思是让每个人更新自己的容器。

      【讨论】:

      • 感谢您的建议。我试过你的代码,但你说得对,那就是容器有问题。下面的代码虽然有效,但这里只有一个值数组:
      • 这看起来是个不错的方法。
      • $.each(jArray, function(i, val) { setTimeout(function() { $('#reklame2').fadeOut("slow", function() { $(this). text(val).fadeIn("slow"); }); $('#reklame17').fadeOut("slow", function() { $(this).text(val).fadeIn("slow"); }); }, i * 6000); });
      • @user2374903:目的是什么?每个partnr 应该更新一个单独的容器,还是它们都意味着按顺序运行?或者应该是partnr1[0] -&gt; partnr2[0] -&gt; partnr1[1] -&gt; partnr2[1] -&gt; etc
      • 抱歉没有明确迭代对象。每次partnr出现时,所有对应的模型都会在那个时刻以列表的形式淡入。
      【解决方案6】:

      我会使用标准的 javascript:

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

      注意处理对象和数组的不同方式。

      【讨论】:

      • 为什么?而你省略了必要的闭包……
      • 它更快,在我看来更干净。我跳过了其余部分,因为我不清楚它应该做什么。 #variant 是什么? #variant 最终应该做什么?
      • #variant 是一个 div 的 id,它将与地图中的信息一起显示(淡入)。对于每个合作伙伴,都应该在一个包含相应模型的列表中淡出。
      猜你喜欢
      • 1970-01-01
      • 2018-02-14
      • 2011-03-23
      • 1970-01-01
      • 2020-10-23
      • 2011-12-22
      • 1970-01-01
      相关资源
      最近更新 更多