2015-12-17 60 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