关联数组对象的Javascript foreach循环

时间:2013-09-14 17:42:16

标签: javascript arrays foreach

为什么for for-each循环不会迭代我的JavaScript关联数组对象?

// defining an array
var array = [];

// assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

编辑:jQuery each()可能会有所帮助:https://api.jquery.com/jQuery.each/

10 个答案:

答案 0 :(得分:282)

.length属性仅跟踪带有数字索引(键)的属性。你正在使用字符串作为键。

你可以这样做:

var arr_jq_TabContents = {}; // no need for an array

arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;

for (var key in arr_jq_TabContents) {
    console.log(arr_jq_TabContents[key]);
}

为了安全起见,在循环中这是一个好主意,以确保没有任何属性是意外的继承结果:

for (var key in arr_jq_TabContents) {
  if (arr_jq_TabContents.hasOwnProperty(key))
    console.log(arr_jq_TabContents[key]);
}

编辑 - 现在可能需要注意Object.keys()功能在现代浏览器和Node等中可用。该函数返回对象的“自己”键,作为一个数组:

Object.keys(arr_jq_TabContents).forEach(function(key, index) {
  console.log(this[key]);
}, arr_jq_TabContents);

调用传递给.forEach()的回调函数,每个键和Object.keys()返回的数组中的键索引。它也传递了函数迭代的数组,但是这个数组对我们并没有用;我们需要原始的对象。这可以通过名称直接访问,但是(在我看来)显式传递它会更好一点,这是通过将第二个参数传递给.forEach() - 原始对象 - 将被绑定为{{1回调内部。 (刚刚看到下面的评论中注明了这一点。)

答案 1 :(得分:66)

这是一种非常简单的方法。优点是你也可以获得钥匙:

for (var key in array) {
    var value = array[key];
    console.log(key, value);
}

对于ES6:

array.forEach(value => {
  console.log(value)
})  

对于ES6 :(如果你想要值,索引和数组本身)

array.forEach((value, index, self) => {
  console.log(value, index, self)
})  

答案 2 :(得分:4)

arr_jq_TabContents[key]将数组视为0索引形式。

答案 3 :(得分:4)

已经有一些直截了当的例子,但是我注意到你的问题是如何提出你可能来自PHP背景的问题,并且你期望JavaScript以相同的方式工作 - 它不会。 PHP array与JavaScript Array非常不同。

在PHP中,关联数组可以完成数字索引数组的大部分工作(array_*函数可以工作,你可以count(),等等。)你只需创建一个数组并开始分配字符串索引而不是数字。

在JavaScript中,一切都是对象(除了原语:string,numeric,boolean),而数组是一个允许你拥有数字索引的特定实现。推送到数组的任何内容都会影响其length,并且可以使用数组方法(mapforEachreducefilter,{{1但是,因为一切都是一个对象,所以你总是可以自由地分配属性,因为这是你对任何对象做的事情。方括号表示法只是访问属性的另一种方式,因此在您的情况下:

find

实际上相当于:

array['Main'] = 'Main Page';

根据您的描述,我的猜测是您想要一个关联数组&#39;,但对于JavaScript,这是一个使用对象作为hashmap的简单情况。另外,我知道这是一个例子,但是避免使用仅描述变量类型的无意义名称(例如array.Main = 'Main Page'; ),并根据它应包含的内容命名(例如array)。简单的对象没有很多好的直接迭代方法,因此我们通常会先使用pages方法转换为数组(在这种情况下为Object - 那里有's}&#39}此外,Object.keysentries也被添加到某些浏览器中,我们可以循环播放。

values

答案 4 :(得分:3)

这是一种将关联数组用作通用对象类型的简单方法:

Object.prototype.forEach = function(cb){
   if(this instanceof Array) return this.forEach(cb);
   let self = this;
   Object.getOwnPropertyNames(this).forEach(
      (k)=>{ cb.call(self, self[k], k); }
   );
};

Object({a:1,b:2,c:3}).forEach((value, key)=>{ 
    console.log(`key/value pair: ${key}/${value}`);
});

答案 5 :(得分:2)

如果node.js或浏览器支持Object.entries(),则可以替代使用Object.keys()https://stackoverflow.com/a/18804596/225291)。

const h = {
  a: 1
  b: 2
};

Object.entries(h).forEach(([key, value]) => console.log(value));
// => 1
// => 2

在此示例中,forEach使用数组的Destructuring assignment

答案 6 :(得分:0)

var obj = {
    no : ["no",32],
    nt : ["no",32],
    nf : ["no",32,90]
};
count = -1; // which must be static value
for(i in obj){ 
   count++;
   if(obj.hasOwnProperty(i){
        console.log(obj[i][count])
      };
};

在这段代码中,我使用了括号方法来调用数组中的调用值,因为它包含数组,但是简单地说,变量i具有属性键和带有关联数组的两个值的循环的想法

完美方法, 如果你有兴趣, 按下

答案 7 :(得分:0)

在大多数情况下(基本上),这是不正确的:

var array = [];
array["Main"] = "Main page";

这将在名称为Main的数组上创建一个非元素属性。尽管数组是对象,但通常您不想在其上创建非元素属性。

如果要通过这些名称索引到array,通常会使用Map或普通对象,而不是数组。

使用Map(ES2015 +),我将其称为map,因为我很有创造力:

let map = new Map();
map.set("Main", "Main page");

然后,您可以使用其valueskeysentries方法中的迭代器对其进行迭代,例如:

for (const value of map.values()) {
    // Here, `value` will be `"Main page"`, etc.
}

使用一个普通对象,我将其创造性地称为obj

let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`

然后,您可以使用Object.keysObject.valuesObject.entries来迭代其内容,例如:

for (const value of Object.values(proches_X)) {
    // Here, `value` will be `"Main page"`, etc.
}

答案 8 :(得分:0)

您可以这样做

#load pROC
library(pROC)
library(dplyr)
library(purrr) #For map2 function

#generate df with random numbers
set.seed(123)
df <- data.frame(disease_status = rbinom(n=100, size=1, prob=0.20),
                 test1 = rnorm(100, mean=15, sd=4),
                 test2 = rnorm(100, mean=30, sd=2),
                 test3 = rnorm(100, mean=50, sd=3))

#create roc object for test1, test2, test3
roc.out_test1<-roc(df$disease_status, df$test1, plot=TRUE, smooth = FALSE)
roc.out_test2<-roc(df$disease_status, df$test2, plot=TRUE, smooth = FALSE)
roc.out_test3<-roc(df$disease_status, df$test3, plot=TRUE, smooth = FALSE)

#compare the AUC of test1 and test 2
roc.test(roc.out_test1, roc.out_test2, reuse.auc=TRUE, method="delong", na.rm=TRUE)

roc_new <- function(test1,  test2){
  roc.test(test1, test2, reuse.auc=TRUE, method="delong", na.rm=TRUE)
}

#List of all tests
all_tests <- list(roc.out_test1,
                  roc.out_test2,
                  roc.out_test3) 

#Create unique combos of tests
unique_combos <- expand.grid(1:3, 1:3) %>% 
  filter(Var1 < Var2) %>% #exludes duplicate comparisons, 
                      #each col provides the index for the 2 lists to iterate over
  mutate(names = paste(Var1, " V ",  Var2)) #Create col to name final output list


#Create 2 lists to iterate over
#Create list 1
(test1 <- all_tests[as.numeric(unique_combos$Var1)])
#Create list 2
(test2 <- all_tests[as.numeric(unique_combos$Var2)])

#Iterate over both lists
output <- map2(test1, test2, roc_new)
names(output) <- unique_combos$names

答案 9 :(得分:-1)

使用数字键。 T* newArray = new T[m_size]; std::copy(m_array, m_array + m_size, newArray); delete[] m_array; m_array = newArray; 上的length仅跟踪数字键。使用ArrayMap s作为键值对。

Object