2014-01-11 199 views
2

我有大約30個對象的數組。每個對象都有一個名爲'註冊'的屬性。註冊屬性是我用來唯一標識每個對象的。每個對象還包含一個時間戳(始終是唯一的)。檢查數組是否包含具有特定屬性值的對象

每隔30秒我從API下載這30個對象的新實例。有可能新對象將被添加到當前數組中。我需要想出一種檢查新對象是否位於舊(當前)對象數組中的方法。如果這些對象不包含唯一的時間戳,那麼這將非常簡單,但是對於每個實例而言,這都不起作用。

我到目前爲止有:

newDownloadedArray = JSON.parse(newDownloadedArray); 

for (var i = 0; i < currentArrayObjects.length; i++) { 
    for (var j = 0; j < newDownloadedArray.length; j++) { 

     /* 
     * This is where I'm stuck. 
     * I now need to check if newDownloadedArray[j].registration is 
     * the value of any registration property inside the currentArrayObjects 
     * array. 
     * 
     * If it is, then I know this is a new object. 
     */ 

    } 
} 

回答

2

這裏是一個解決方案:

var isNewObject = function(newObject) { 
    return !currentArrayObjects.some(function(currentObject) { 
     return newObject.registration == currentObject.registration; 
    }); 
}; 
var onlyNewObjects = newDownloadedArray.filter(isNewObject); 

我們基本上說:「對於每newDownloadedArray對象,看看每一個對象在currentArrayObjects直到找到其中一個匹配registration,如果這樣做,該對象包含在onlyNewObjects中,如果不包含,則不包含。

請注意,Array.prototype.filterArray.prototype.some僅適用於IE 9+,因此如果您希望支持舊瀏覽器,則可能需要使用等效的輔助方法或實用程序庫(如underscore)。

這不是非常有效。對於包含30個項目的數組,我們正在做最差情況900次的工作(如果新陣列是完全唯一的,因爲它必須搜索newDownloadedArray中的每一個的所有30個currentArrayObjects)。

但這在瀏覽器方面並不是很多。你可以做很多工作來加速它。例如,而不是在謂語通過currentArrayObjects搜索,我們可以與所有的註冊建立一個對象:

// We want a set of registrations, but JavaScript doesn't 
// have a native set class, so we're going to use the keys 
// of an object to simulate sets, because object keys are 
// basically sets of strings. Note that this won't work if 
// registration isn't a string. 
var currentRegistrations = {}; 
currentArrayObjects.forEach(function(currentObject) { 
    // AKA currentRegistrationSet.add(currentObject.registration) if we 
    // had an actual set class. I chose 'true' somewhat at random 
    // because it felt right; we'll never actually be accessing 
    // the value. 
    currentRegistrations[currentObject.registration] = true; 
}); 
var isNewObject = function(newObject) { 
    // AKA !currentRegistrationSet.contains(newObject.registration) if we 
    // had an actual set class. 
    return !currentRegistrations.hasOwnProperty(newObject.registration); 
} 
var onlyNewObjects = newDownloadedArray.filter(isNewObject); 

(同樣告誡約Array.prototype.forEach

現在,我們只需要做大約60次 - - 30提前構建對象,另外30個來檢查每個對象。


您的解決方案與我發佈的第一個項目並不遙遠。但是你切換了for循環。它可能是:

newDownloadedArray = JSON.parse(newDownloadedArray); 

var onlyNewObjects = [] 
for (var i = 0; i < newDownloadedArray.length; i++) { 
    var isNewObject = true; 
    for (var j = 0; j < currentArrayObjects.length; j++) { 
     if (newDownloadedArray[i].registration == currentArrayObjects[j].registration) { 
      isNewObject = false; 

      break; // no reason to keep looking; we know it isn't new 
     } 
    } 
    if (isNewObject) { 
     onlyNewObjects.push(newDownloadedArray[i]); 
    } 
} 
+0

謝謝您的回答!爲了記錄,我選擇了將自己陣列中的所有註冊存儲的路線,以保持簡單。這確實意味着必須管理另一個單獨的陣列,但我認爲出於速度和組織的目的,這是此場景的絕佳選擇。 – jskidd3

+0

@ jskidd3您應該查看我添加到第二個解決方案的註釋。將註冊存儲在數組中並不可怕,但您真正想要的是將註冊存儲在一個集合中 - 搜索數組是O(n);搜索哈希集是恆定的時間。 –

0

如果您不介意使用lo-dash

這裏有一個fiddle

var newRegistrations = _.difference(
     _.pluck(newDownloadedArray, 'registration') 
     , _.pluck(currentArrayObjects, 'registration') 
); 
相關問題