2010-06-25 37 views
1

我正在使用PHP從我的數據庫中獲取「任務」並將其編碼爲JSON。當我在傳輸數據的JavaScript,我結束了這樣的事情:如何迭代JavaScript中的對象數組?

Array { 
    [0] => Task { 
     id: 2, 
     name: 'Random Task', 
     completed: 0 
    } 
    [1] => Task { 
     id: 8, 
     name: 'Another task', 
     completed: 1 
    } 
} 

我想我真正的問題是,什麼是要找到它的id任務的最有效方法是什麼?遍歷數組並檢查每個對象似乎可能不是最高效的?有沒有其他方法可以做到這一點?

+0

你能發佈確切的JSON響應嗎? – 2010-06-25 06:34:31

+3

如果你總是通過id訪問,那應該是關鍵。 – 2010-06-25 06:35:05

+0

我也可能正在訪問完成,或文件夾(我只包括最基本的例子) – Rob 2010-06-25 06:36:51

回答

6

Javascript對象的事情是它們是必不可少的地圖。您可以通過同時使用點符號(「object.property」)和索引符號(「object [」property「])來訪問屬性。也可以使用for(i ...)或for (以...)

for (var i = 0; i < arrayObj.length; i++) { ... } 

for (var prop in arrayObj) { ... } 

我所最近一直在做的一些建設Linq的去年秋季擴展到數組對象:

Array.prototype.Where = function(predicate) { 
    Throw.IfArgumentNull(predicate, "predicate"); 
    Throw.IfNotAFunction(predicate, "predicate"); 

    var results = new Array(); 
    for (var i = 0; i < this.length; i++) { 
     var item = this[i]; 
     if (predicate(item)) 
      results.push(item); 
    } 

    return results; 
}; 

無視我的自定義投擲型,它基本上可以讓你做的例如:

var item = arrayObj.Where(function(i) { return (i.id == 8); }).FirstOrDefault(); 

如果您有興趣,我會在某些時候發佈它?

+0

我喜歡這個主意。我正在考慮寫一些類似的東西,如: Array.findObjectByKey('key','val'); 我想這只是有道理的,我必須迭代整個數組,如果我想找到我需要的東西。 – Rob 2010-06-25 06:48:32

+0

好吧給我幾個小時,然後我會在我的博客上發佈它,這樣你就可以使用我製作的所有方法? – 2010-06-25 07:02:55

+0

聽起來不錯,謝謝。 – Rob 2010-06-25 07:09:01

2

通常,在Javascript中迭代數組集合的最有效方法是堅持原生for循環。我說「通常」的原因是,實現歸結爲每個獨特的瀏覽器的JavaScript實現,所以沒有絕對的明確答案。

http://solutoire.com/2007/02/02/efficient-looping-in-javascript/有一個很好的帖子,涵蓋了每個主要迭代方法的性能,並憑經驗得出了相同的結論。

+0

感謝您的信息,我想我會寫一些功能,做我需要使用for循環 – Rob 2010-06-25 06:56:01

0

如果id是唯一的(並且大部分是連續的),則可以對數組進行一次重新排列,以便數組索引反映id。如果它們不是唯一的,則可以對它們進行排序並進行二分查找。

但是,只有當你頻繁地從數組中訪問id項時,這是有用的,否則排序的開銷將不值得。

+0

事情是,id可能根本不連續。將會有成千上萬的任務,因此給定用戶的任務可能從1或2000開始,包括任何介於兩者之間的任務。我搞亂了使用id作爲索引的想法,但後來我調試了這個數組並發現瞭如下內容: ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,, 40 ,,,,,,,,,,,,等 – Rob 2010-06-25 06:43:08

0

你的陣列很大嗎?如果沒有,那麼優化它可能不會贏得很多微妙的時間。

如果它很大,你應該真的返回一個字典(正如Matthew Flaschen所評論的),它使用任務的ID作爲關鍵字。通過這種方式,您將獲得持續時間查詢(至少如果JavaScript實現是最佳的)。

只需使用一個普通的PHP關聯數組,並通過json_encode或任何你正在使用的運行。

//Assume you have your original Array named $tasks: 
$dictionary = Array(); 
foreach($tasks as $task) 
    $dictionary[$task->getID()] = $task; 
2

如果你不需要維護順序,那麼最好的方法是對一個普通的對象,並通過任務id索引。這給你O(1)訪問權限。

var tasks = { 
    '2': { 
     id: 2, 
     name: 'Random Task', 
     completed: 0 
    }, 
    ... 
} 

如果您還需要訂餐保持,然後寫通過創建任務ID數組維持秩序的OrderedMap「下課」,但實際的任務仍然會存儲在任務ID索引的對象。所以基本上你會:

// internal API (to help maintain order) 
taskIDs = [a, b, c, ..]; 
// internal API (for actual storage) 
tasks = { 
    a: { .. }, 
    b: { .. }, 
}; 

// external API for iterating objects in order 
forEach(fn); 
// external API for accessing task by ID 
get(id); 

外界可以無知的你如何維持秩序,只要你提供,以便這些迭代,並通過任務ID訪問它們的一個很好的封裝方式。

如果您需要參考以實施此類課程,請參閱source(來自Google Closure Library的LinkedMap)。

2

只是爲了想多一點的食物,這是我結束了:

this.find = function (test) { 
    var results = []; 
    for (var i = 0,l = this.tasks.length; i < l; i++) { 
     var t = this.tasks[i]; 
     if (eval(test)) { 
      results.push(this.tasks[i]); 
     } 
    } 
    return results; 
} 

這允許我做一個簡單的tasks.find(「t.id == 2」)或任務。 find('t.completed == 1');

+2

+1好的解決方案..我對此做了一個改變,它將eval測試包裝在with語句中,因此調用客戶端不必擔心你在裏面調用了那個臨時變量。他們可以簡單地做'tasks.find(「id == 2」)'..嘲笑一個例子 - http://jsfiddle.net/GQ5RQ/ – Anurag 2010-06-25 23:16:05