【问题标题】:Javascript: Iterating over array with non-consecutive keysJavascript:使用非连续键迭代数组
【发布时间】:2012-02-22 09:39:33
【问题描述】:

我需要遍历一个键不连续的数组:

var messages = new Array();
messages[0] = "This is the first message";
messages[3] = "This is another message";

显然使用 for 循环的索引是行不通的,因为它取决于键的顺序:

for (var i=0 ; i<messages.length ; i++) {
    alert(messages[i]); // Will only alert the first message, as i is never equal to 3
}

处理此问题的规范方法是什么,例如the for-each syntax is not intended for iterating over values in an array in javascript?谢谢。

【问题讨论】:

  • 你最初是如何得到这样一个数组的?与其寻找一些技巧来迭代它,为什么不从根本上解决问题 => 这就是你获得这个数组的方式。
  • 您是否考虑过使用对象来代替? { "0": "this is the first message", "3": "this is another message"}
  • 只会提醒第一条消息,因为 i 永远不会等于 3 这是不正确的。 messages.length 将是 4
  • 数组代表对象,而不是示例中的简单字符串文字。数组键是数据库主键。将主键作为对象的另一个属性会导致各种复杂性,因为我通常知道通过 ID 访问哪个对象,因此将 ID 作为数组键非常方便。也就是说,除了这一问题。
  • @Yoshi:你是对的,循环必须抛出异常并在遇到无效数组键时退出。无论哪种方式,这种方法都行不通!

标签: javascript jquery oop iterator


【解决方案1】:

惯用的方法是使用对象,而不是数组。请务必检查hasOwnProperty 以确保您不会拾取可能已添加到原型中的杂散东西。

var messages = { };
messages[0] = "This is the first message";
messages[3] = "This is another message";

for (var i in messages) {
    if (messages.hasOwnProperty(i))
        alert(messages[i]); 
}

或者,更现代的方式是使用Object.keys

Object.keys(messages).forEach(prop => {
    alert(messages[prop]);
});

如果您打算在 IE 等旧版浏览器中运行该代码,请务必使用 Babel 转译该代码。

【讨论】:

  • ... 挤进hasOwnProperty() 支票会增加这个答案的魅力。
  • 为什么不直接在消息上调用hasOwnPropertyif( messages.hasOwnProperty( i ) ) { alert( messages( i ) ); }
  • @meouw - 这只是一个额外的安全措施,但可能是不必要的预防措施,以保护您免受消息定义名为 hasOwnProperty - {}.hasOwnProperty.call 的属性或函数的微小可能性的影响,确保您将总是在 object.prototype 上得到一个
  • OK - 我认为这让问题有点模糊。您的答案并不像可能的那样清楚,因为您不仅要解决 OP 的问题,还要解决另一个问题。
  • 感谢您回答这个问题,这仍然让我感到困惑,一些堆栈社区如何决定开始提出不相关的问题或告诉您的错误但未能给您充分的理由。
【解决方案2】:
for(var i in messages)
{
    console.log(messages[i]);
}

【讨论】:

  • 谢谢,我看到console.log() 是一个相当强大的工具!
【解决方案3】:

您可以忽略 undefined 属性...

for (var i=0 ; i<messages.length ; i++) {
    if(messages[i] !== undefined)
        alert(messages[i]);
}

或者使用forEach,会忽略undefined未声明的属性...

messages.forEach(function(v,i) {
    alert(v);
});

【讨论】:

  • ohhh - forEach +1 - 不知道忽略了未定义的属性。
  • forEach 没有在 IE
  • @Tim - 是的......我想我只是(通常)有幸无视这个事实:)
  • 需要明确的是,forEach 不会忽略值为 undefined 的元素。如果你说messages[n] = undefined然后调用messages.forEach()n处的元素将被处理。相反,forEach 会跳过 Array 中不存在任何元素的索引。通过测试if (i in messages)可以使用相同的逻辑。
  • @gilly3:你是对的。未声明会是一个更好的词。
【解决方案4】:

您可以使用each() jQuery 方法来做到这一点。

$.each(messages, function(index, val){
    alert(val); 
});

来自 jQuery 文档

each()

一个通用的迭代器函数,可以用来无缝迭代 在对象和数组上。数组和类数组对象 长度属性(例如函数的参数对象)被迭代 按数字索引,从 0 到 length-1。其他对象通过迭代 它们的命名属性。

【讨论】:

  • “jQuery”真的是简单枚举的最佳解决方案吗?
  • @ShankarSangoli,你发现$.each(messages, function(index, val){for (var i in messages) { 更简单?我想我们对简单有不同的定义。
  • 我认为使用基本语言结构“for”比使用jQuery.each更干净而且更简单
  • 因为jQueryindexvalue 作为回调参数分开,所以您不必维护变量。如果性能是问题,我肯定会使用经典的 JavaScript 方式使用 forforEach
【解决方案5】:

当您创建一个数组并在03 处为其赋予值时,undefined 值将在12 处创建。试试这个:

$.each(messages, function(i,val) { 
  if (val) {
    alert(val);
  } 
});

【讨论】:

  • “jQuery”真的是简单枚举的最佳解决方案吗?
  • 这取决于你认为什么是“最好的”。对于正在学习 javascript 并可以访问 jquery 的人来说,使用 jquery 每个都可以避免使用 for 循环时发现的其他常见问题,而不知道它们是如何工作的。
  • 如果您只看到“最快”,最好不要使用 javascript 库,对吧?
  • @Matt - 这里的真正答案是,当您创建一个值为03 的数组时,12 的索引将被填充并迭代。他的原始代码将提醒所有消息。你如何迭代它们并不重要。
  • 当你创建一个值为 0 和 3 的数组时,1 或 2 处没有元素。并不是 1 和 2 处的元素包含值undefined。索引 1 和 2 处根本没有元素。在 JavaScript 控制台中试试这个:var a = [1]; a[3] = 1; console.log(1 in a);
【解决方案6】:

简单!如果数组在索引之间有规则的间隙,请执行以下操作:

for (var i = 0 ; i < messages.length; i += gap) {
    alert(messages[i]); // Will only alert the messages at the regular interval/gap 
}

【讨论】:

  • 虽然这适用于恒定的间隙,但 OP 声明键是非连续的,这与具有恒定间隙不同。
  • 不一样但包括这个案例,然后是它的代码,我在答案的一开始就明确说明了。
【解决方案7】:

对于带有假设的用例:

array.length &gt;== 1 (即:一个已经包含有意义数据的数组)

您对来自array[1], array[15], array[45]等的数据感兴趣的地方

你可以做类似的事情:

var array = ["you","will","become","strong","with","the","codes","padawan"];
var values = [1,5,7];


for (var i = 0; i < values.length; i++){
    var cypher = values[i];
    console.log(array[cypher]);
}
//will, the, padawan

或者更有意义的东西,例如:

for (var i = 0; i < values.length; i++){
    var cypher = values[i];
    aService.aFn.(array[cypher],cb);
}
//calls aService.aFn separately for each value array[1] , array[5] , array[7] passed as args

【讨论】:

    猜你喜欢
    • 2011-10-30
    • 1970-01-01
    • 2015-03-30
    • 2015-05-27
    • 2011-01-31
    • 1970-01-01
    • 2015-03-14
    • 2017-02-09
    • 1970-01-01
    相关资源
    最近更新 更多