2015-12-17 48 views
4

我有一个JSON对象数组,我想找到具有某个属性的对象。我知道这可能看起来像重复的问题,但请继续,因为我认为它与以前的问题略有不同。JavaScript中的IndexOf方法比遍历数组更有效吗?

与我合作的人建议使用IndexOf,这让我想到了。有没有类似于mongo中的$ elemMatch功能?是否有一些命令基本上用伪代码表示“用这个属性从这个数组中获取对象”?通过迭代,我觉得伪代码说:“看看这个数组中的第一个对象,如果这个对象有这个属性,请把这个对象给我,如果没有,看看这个数组中的第二个对象..... “

我明白如何使用IndexOf就像我的朋友建议的那样,但我越想到它,我开始认为IndexOf方法可能是更少的代码行,但它最终不必遍历对象在数组中找到我需要的索引?所以,如果我想用这个属性对对象做些什么,并且我使用IndexOf方法来获取索引,那么我会引用像myArray [indexFromIndexOfMethod]这样的对象,然后相应地修改它,是否正确?所以,如果javascript迭代数组本身来执行IndexOf方法,为什么不写我自己的迭代并保存一个步骤?现在,如果IndexOf方法使用更有效的定位数组元素的方法,而不是遍历并检查每个元素,那么使用它就有意义。否则,如果通过简单的迭代可以获得相同的结果,则使用IndexOf方法是没有意义的。

+0

我需要一个更好的解释,为什么它使用'indexOf'是不合理的,因为你可以编写自己的迭代和已经写好的代码。 –

+0

不知道如何不使用'indexOf'会为你节省任何东西。有了它,你不必编写循环,它为你做循环。 –

+0

但是我想要使用该对象的操作可能发生在对象位于数组中的那一刻。所以如果我写我自己的迭代,我可以将所有这些东西添加到函数中。如果我使用IndexOf,那么javascript会做任何事情来查找我正在查找的元素的索引,然后当完成时,我可以使用生成的索引来获取该对象。所以如果IndexOf不比迭代更有效,我可以将这两个步骤合并为一个。 – bigchrisf

回答

1

Array.prototype.indexOf也只是遍历数组,并返回第一个索引与匹配的值。你可以用循环做同样的事情。它可能是可能是或者可能不会比for循环略快,因为indexOf可以在本机代码中实现,并且优化方式与您的for循环不同,但没有根本区别。

如果你经常需要尽可能快地访问特定值,那么值得在对象中通过该值来索引它们。也就是说,如果你想通过其属性.foo找到一个特定的对象的时候,这样做:

var byFoo = {} 
for (var i = 0; i < myArray.length; i++) { 
    byFoo[myArray[i].foo] = myArray[i]; 
} 

这就允许您使用byFoo['baz']即时访问。

当然,这可能会在多个副本中维护这些索引的额外开销,但它会加快数组访问的速度。你需要权衡利弊。

+1

谢谢你很好的答案。我可以告诉你,你完全理解我在问什么,我不觉得这里有其他人。有时候可能会更好地阅读一个问题几次以获得对它的全面理解,而不是快速浏览它并试图获得第一个答案。 – bigchrisf

+0

那么,如果问题更加紧凑并且包含代码示例,它*将会有所帮助... :-P – deceze

+0

@ChristopherFlint \t我想每个人都明白你的问题。我们不明白的是,你通过在循环中编写代码,在发现有问题的值之后突破循环,等等来复制'indexOf'功能,从而理解“储蓄”。 –

1

如果对象是实际对象,indexOf将无法在对象上工作,因为即使它们具有相同的属性值,两个对象也将不同于对方,因此您不能将实际对象用作indexOf的输入。

它只会在JSON仍未解析的字符串时才起作用,那么它将是最有效的方法。

因此,如果我必须直接引用对象,我倾向于使用的解决方案是使引用包含每个对象的索引,或者仅使用对象而不是数组来存储数据对象,一个唯一的标识符,如数据对象的id,作为键。

// This will fail: 
var data = [ 
    { 
     'id' : 1, 
     'value' : 'myDataForObj1' 
    }, 
    { 
     'id' : 2, 
     'value' : 'myDataForObj2' 
    } 
]; 

data.indexOf({ 
    'id' : 2, 
    'value' : 'myDataForObj2' 
}); // return -1, as in, not found. 


// This will work: 
var data = [ 
    '{"id":1,"value":"myDataForObj1"}', 
    '{"id":2,"value":"myDataForObj2"}' 
]; 

data.indexOf('{"id":2,"value":"myDataForObj2"}'); // return 1, as in the second element in the array. 

// This is what I usually use: 
var data = { 
    'id1' :  { 
     'id' : 1, 
     'value' : 'myDataForObj1' 
    }, 
    'id2' : { 
     'id' : 2, 
     'value' : 'myDataForObj2' 
    } 
}; 

data['id2'].value = 'newValue'; 

你必须做出一些方式来引用您想直接访问,虽然一切,所以如果你希望能够找到任何对象的任何值,循环可能会更容易实现对物体具有很多属性。

因此,我已经习惯了总是有一些'id'与我必须操纵的数据相关联。例如,最终用户点击表格中的一行来编辑它。我将确保该行有一个data-attribute,它引用了数据在模型中的id,它将与它在后端的id相同。在大多数情况下,这种设计消除了迭代数据存储的需要。

+1

谢谢我欣赏这个答案,如果我可以选择两个最好的答案,我会选择你的。不幸的是,下一个人更好地回答了我的具体问题。 – bigchrisf