2012-05-11 131 views
93

我一直在衝浪,試圖找到一種有效的方法來做到這一點,但無處可去。我有對象的數組,看起來像這樣:在對象數組中,找到屬性匹配搜索對象的索引的最快方法

array[i].id = some number; 
array[i].name = some name; 

我想要做的是找到其中id等於對象的索引,例如,0,1,2,3一個或4. 我想我可以這樣做:

var indexes = []; 
for(i=0; i<array.length; i++) { 
    (array[i].id === 0) ? { indexes[0] = i } 
    (array[i].id === 1) ? { indexes[1] = i } 
    (array[i].id === 2) ? { indexes[2] = i } 
    (array[i].id === 3) ? { indexes[3] = i } 
    (array[i].id === 4) ? { indexes[4] = i } 
} 

雖然這工作,看起來是相當昂貴的,緩慢的(更不用說醜),特別是如果array.length可能很大。任何想法如何使這一點變得更好?我想以某種方式使用array.indexOf,但我看不到如何強制語法。這

array.indexOf(this.id === 0); 

例如,返回未定義,因爲它可能應該。 在此先感謝!

+1

如果你有一個普通的舊的陣列,你可以做一個新的方式回報指數1正在迭代。這就是數組,是由數組索引排序的一堆對象。 –

+2

今天剛剛遇到這篇文章,對於所有後來者來說,ECMAScript 2015中有一個新的數組方法'Array.prototype.findIndex()'。接受的答案非常棒。 –

回答

311

也許你想使用更高階的函數,如「地圖」。 假設你想通過「場」屬性進行搜索:

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor); 
var objectFound = array[elementPos]; 
+6

這個答案很好,因爲它實際上通過提供索引來回答問題:) – counterbeing

+0

對於一個標準,這是正確的,但是如果需要比較多個標準呢? – eKelvin

+3

@ZeroAbsolute你的應用函數(傳遞給map)可以返回一個散列字符串,它應該爲你的標準給出的每個可能的組合提供一個唯一的鍵。例如:'function hashf(el){return String(el.id)+「_」+ String(el.name); }'。這只是一個提示:'elementPos = array.map(hashf(x))。indexOf(hash({id:3,name:'Pablo'}));'很明顯,我提供的散列函數對所有因爲''_''可能構成你的值的一部分,但它只是一個快速的例子,你可以找出不同的散列方法。 –

6
var indices = []; 
var IDs = [0, 1, 2, 3, 4]; 

for(var i = 0, len = array.length; i < len; i++) { 
    for(var j = 0; j < IDs.length; j++) { 
     if(array[i].id == ID) indices.push(i); 
    } 
} 
2

聽起來像我可以創建一個簡單的迭代器與測試回調。像這樣:

function findElements(array, predicate) 
{ 
    var matchingIndices = []; 

    for(var j = 0; j < array.length; j++) 
    { 
     if(predicate(array[j])) 
      matchingIndices.push(j); 
    } 

    return matchingIndices; 
} 

然後,你可以調用像這樣:

var someArray = [ 
    { id: 1, text: "Hello" }, 
    { id: 2, text: "World" }, 
    { id: 3, text: "Sup" }, 
    { id: 4, text: "Dawg" } 
    ]; 

var matchingIndices = findElements(someArray, function(item) 
    { 
     return item.id % 2 == 0; 
    }); 

// Should have an array of [1, 3] as the indexes that matched 
25

新的數組方法.filter()會爲這項工作做得很好:

var filteredArray = array.filter(function (element) { 
    return element.id === 0; 
}); 

jQuery的也可以用.grep()

做到這一點

編輯:值得一提的是,這些fu nctions只是在引擎蓋下進行迭代,它們之間不會有明顯的性能差異,並且可以滾動自己的過濾器功能,但爲什麼要重新發明輪子。

+0

+1,我總是忘記在對象上構建這樣的函數。 – Tejs

+49

這不會返回索引。 –

+0

這並不回答這個具體的問題,但幫助我很多!謝謝! – rochasdv

7
array.forEach(function (elem, i) { // iterate over all elements of array 
    indexes[elem.id] = i;   // take the found id as index for the 
});         // indexes array and assign i 

結果是id的查找表。用給定的id我們得到記錄的索引。

2

適應TEJS的答案的MongoDB和Robomongo我改變

matchingIndices.push(j); 

matchingIndices.push(NumberInt(j+1)); 
21

找到的數組元素索引的最簡單和最簡單的方法。

ES5語法:[{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

ES6語法:[{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)

+1

我相信這是最優雅的解決方案。對於那些擔心向後兼容的人,你可以在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex – mrogers

0

正如我尚未對此發表評論,我想表明我使用的解決方案基於該方法Umair艾哈邁德發佈,但是當你想搜索一個密鑰,而不是一個值:

[{"a":true}, {"f":true}, {"g":false}] 
.findIndex(function(element){return Object.keys(element)[0] == "g"}); 

我知道它不回答擴展的問題,但標題沒有具體說明每個對象需要什麼,所以我想謙虛地分享這個以便將來爲其他人避免頭痛,而我未開啓它可能不是最快的解決方案。

2

使用ES6 map功能:

let idToFind = 3; 
let index = someArray.map(obj => obj.id).indexOf(idToFind); 
+0

找到'findIndex'的polyfill這對我很好,謝謝! – Jay

2

既然沒有答案使用規則排列find

var one = {id: 1, name: 'one'}; 
var two = {id: 2, name:'two'} 
var arr = [one, two] 

var found = arr.find((a) => a.id === 2) 

found === two // true 

arr.indexOf(found) // 1 
2

要總結上述所有偉大的答案,並就發現所有的附加我的回答索引從一些評論發生。

  1. 要返回首次出現的索引。

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }]; 
 
const idYourAreLookingFor = 2; 
 

 
//ES5 
 
//Output: 1 
 
array.map(function (x) { return x.id; }).indexOf(idYourAreLookingFor); 
 

 
//ES6 
 
//Output: 1 
 
array.findIndex(obj => obj.id === idYourAreLookingFor);

  • 要返回所有匹配的索引陣列,使用減少。
  • const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }] 
     
    const idYourAreLookingFor = 2; 
     
    
     
    //ES5 
     
    //Output: [1, 4] 
     
    array.reduce(function (acc, obj, i) { 
     
        if (obj.id === idYourAreLookingFor) 
     
        acc.push(i); 
     
        return acc; 
     
    }, []); 
     
    
     
    //ES6 
     
    //Output: [1, 4] 
     
    array.reduce((acc, obj, i) => (obj.id === idYourAreLookingFor) ? acc.concat(i) : acc, [])

    0

    我已經創建了一個名爲super-array小小的工具,你可以用O(1)複雜的唯一標識符訪問數組中的項目。例如:

    const SuperArray = require('super-array'); 
    
    const myArray = new SuperArray([ 
        {id: 'ab1', name: 'John'}, 
        {id: 'ab2', name: 'Peter'}, 
    ]); 
    
    console.log(myArray.get('ab1')); // {id: 'ab1', name: 'John'} 
    console.log(myArray.get('ab2')); // {id: 'ab2', name: 'Peter'} 
    
    +0

    你可能想閱讀[如何提供個人開源庫?](// meta.stackexchange.com/q/229085),然後發佈到處。 –

    +0

    @MartijnPieters我已經發布了它只有幾個相關的問題,該項目是免費的麻省理工學院,這是什麼交易?也許你可以更容忍一點。 – patotoma

    0
    var test = [ 
        {id:1, test: 1}, 
        {id:2, test: 2}, 
        {id:2, test: 2} 
    ]; 
    
    var result = test.findIndex(findIndex, '2'); 
    
    console.log(result); 
    
    function findIndex(object) { 
        return object.id == this; 
    } 
    

    會(僅在ES 2016工程)

    0

    使用ES6

    let picked_element = array.filter(element => element.id === 0);