检查数组是否包含具有特定属性值的对象 [英] Check if array contains an object with the value of a specific property
问题描述
我有一个大约30个对象的数组。每个对象都有一个名为registration的属性。注册属性是我用来唯一标识每个对象的属性。每个对象还包含一个时间戳(总是唯一的)。
I have an array of around 30 objects. Each object has a property called 'registration'. The registration property is what I use to uniquely identify each object. Each object also contains a timestamp (always unique).
每30秒我从API下载这30个对象的新实例。新对象可能会添加到当前数组中。我需要想出一种检查新对象是否在旧(当前)对象数组中的方法。如果对象不包含唯一的时间戳,那么这将非常简单,但由于每个实例都有所不同,这将无效。
Every 30 seconds I download a new instance of these 30 objects from an API. There is a possibility that a new object will be added to the current array. I need to come up with a way of checking if the new object is in the array of old (current) objects. If the objects didn't contain a unique timestamp then this would be very simple but as this varies for every instance this won't work.
到目前为止我所拥有的:
What I have so far:
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.
*/
}
}
推荐答案
这是一个解决方案:
var isNewObject = function(newObject) {
return !currentArrayObjects.some(function(currentObject) {
return newObject.registration == currentObject.registration;
});
};
var onlyNewObjects = newDownloadedArray.filter(isNewObject);
我们基本上说对于中的每个对象> newDownloadedArray
,查看 currentArrayObjects
中的每个对象,直到找到匹配的注册
。如果这样做,该对象包含在 onlyNewObjects
中。如果不包含,则不是。
We're basically saying "For every object in newDownloadedArray
, look at every object in currentArrayObjects
until you find one that has a matching registration
. If you do, that object is included in onlyNewObjects
. If you don't, it isn't.
注意 Array.prototype.filter
和 Array.prototype.some
仅在IE 9+中可用,因此您可能希望使用等效的辅助方法或实用程序库(如下划线)如果你想支持旧的浏览器。
Note that Array.prototype.filter
and Array.prototype.some
are only available in IE 9+, so you might want to use an equivalent helper method or utility library (like underscore) if you want to support older browsers.
这不是很有效。对于30个项目的阵列,我们的工作是最差的900吨imes(如果新数组是完全唯一的,因为它必须为每个 newDownloadedArray $ c搜索所有30个
currentArrayObjects
$ c>)。
This isn't very efficient. For arrays of 30 items, we're doing work a worst-case of 900 times (if the new array was completely unique, because it has to search through all 30 of the currentArrayObjects
for each one of the newDownloadedArray
).
但在浏览器方面,这并不是很多。你可以做很多事情来加速它。例如,我们可以构建一个包含所有注册的对象,而不是在谓词中搜索 currentArrayObjects
:
But that's not really a lot in browser terms. And you can do a lot to speed it up. For example, instead of searching through the currentArrayObjects
in the predicate, we could build an object with all the registrations:
// 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
)
(Same caveat about Array.prototype.forEach
)
现在我们只需要做大约60次操作 - 30次提前构建对象,另外30次来检查每个操作。
Now we only have to do about 60 operations -- 30 to build the object ahead of time, and 30 more to check each one.
您的解决方案与我发布的第一个解决方案相差不远。但是您为循环切换了。它可能是:
Your solution wasn't far off from the first one I posted. But you switched the for
loops. It could be:
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]);
}
}
这篇关于检查数组是否包含具有特定属性值的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!