Better way to get an unique object out of an array - javascript

I have an array with objects. Each object got an unique id. What is the best way to get a specific object from the array?
Currently I use something like this
this.getObjectById = function(objectId){
return $.grep(this.objects, function(e){ return e.id === objectId; })[0];
}
but the fact that
$.grep();
returns an array of results I don't know if I should go for this. Because currently I take the first element of this array and it's fine because I just got one element in it.
But is there a more clean way?
Is
Array.prototype.find()
a better one?

Find is faster since it returns the first match, while jquery grep loops trough entire array. If you need full browser support just create you own function:
this.getObjectById = function(objectId){
for(var i = 0; i<this.objects.length; i++){
if(objectId == this.objects[i].id) return this.objects[i];
}
return null;
}

Use underscore.js _.find() method to iterate your collection.

Related

Angularjs - delete searched object from json array

I'm using a ng-change directive to get an object that change. When i get it i have to check if exists in another array of objects, and if it does i have to delete from it.
what can i do? i tried with indexOf but it didn't work.
//#Param ObjectItem: change object from UI using ng-change
$scope.itemValue = function (ObjectItem) {
//collection of required items
var requiredItem = dataPublicationService.getRequired();
//check if item exist in collection. DIDN'T WORK!
if(requiredItem.indexOf(publi) !== -1){
//get found index
var idx = requiredItem.indexOf(publi);
//delete founded item.
requiredItem.splice(idx, 1);
}
};
What other solution can i implement?
The indexOf function doesn't delete from an array, it just finds the index of the given object if found. You might consider filtering the array and testing for a match, rather than relying on indexOf to find a matching object.
Once you find your record, you need to actually alter the array using something like Array#splice.

Search for an array elements in another array

In my case I have an array object $scope.folderfiles. I select some files from the list and I want to have the index of the selected files in the folderfiles. I've done this :
for (var i=0; i < $scope.selectedfiles.length; i++) {
var pos = $scope.folderfiles.indexOf($scope.selectedfiles[i]);
console.log(pos);
}
but I always get -1. When I bind selectedfiles I get the list I've selected which is included in my folderfiles array
example:
folderfiles: [{"id":135,"name":"dddd","mtime":1429881529000},{"id":136,"name":"qqq","mtime":1429881566000,"size":null}]
selectedfiles: [{"id":135,"name":"dddd","mtime":1429881529000}]
what's wrong ?
indexOf will check for two objects that occupy the same space in memory. I think what you want in this case is angular.equals(obj1, obj2) for the equality comparison.
folderfiles: [{"id":135,"name":"dddd","mtime":1429881529000},{"id":136,"name":"qqq","mtime":1429881566000,"size":null}]
selectedfiles: [{"id":135,"name":"dddd","mtime":1429881529000}]
what's wrong ?
indexOf compares the references of the objects when you apply it to an array of objects.
this would work :
selectedfiles: [folderFiles[0]]
I recommend you to use lodash if you are working with a lot of array logic
_.intersection(selectedFiles, folderFiles).length;

Using indexOf to remove an Object from a list?

So, I have seen this piece of code:
removeOrder = (order) ->
index = listOfOrders.indexOf(order)
if index isnt -1
listOfOrders.splice index, 1
where order is an object like this:
order = {
id: whatever
field1: whatever
...
}
This is working now because the order that is passed as argument is referencing some object in listOfOrders, something like removeOrder(listOfOrders[i]). But my question is, is this safe? I mean, I think it would be better to iterate over the list of orders and search for an object with the same id, for example, and remove it.
As far as I know indexOf is Ok when the object we are searching for is a "simple" object (a number, a string, etc.).
According to These docs for indexOf, indexOf uses strict equality ===.
var a = {id:1};
var b = {id:1};
a === a; // this is true
a === b; // this is false
So its safe to in general for objects
You do need to check that indexOf != -1 before the splice though
var removeOrder = function(order)
{
var index = listOfOrders.indexOf(order);
if (index != -1)
return listOfOrders.splice(index, 1); //for chaining?
return listOfOrders;
}
It's safe to use indexOf if the intended purpose is to remove an object from the array by it's reference.
If you want to remove first object by id let's say, you would use something like:
var removeOrderById = function(orderId)
{
var orders = listOfOrders.filter(function(item)
{
return item.id == orderId;
});
if (orders.length > 0)
{
var index = listOfOrders.indexOf(orders[0]);
return listOfOrders.splice(index, 1); //for chaining?
}
return listOfOrders;
}
Conclusion: it's all about the use case.
The function works as inteded assuming that there is exactly one reference to the object in the array.
If the object isn't in the array (or you are calling it with a clone of an object in the array), the index will be -1 and the splice call will remove the last item in the array instead. As this is not a reasonable behaviour, there should really be a check for that (which I see that you added).
The indexOf method works reliably for object references, but it natually has to be looking for the same object.
Looking for an object with a specific propery value would also work, but it goes with the same assumptions; the value has to occur exactly once in the array to work as intended.

javascript check existence of elements of 1 array inside the other

For searching elements of one array inside the other, one may use the indexOf() on the target of search and run a loop on the other array elements and in each step check existence. This is trivial and my knowledge on Javascript is too. Could any one please suggest a more efficient way? Maybe even a built-in method of the language could help? Although I couldn't hit to such a method using google.
You can use Array.filter() internally and implement a function on Array's prototype which returns elements which are common to both.
Array.prototype.common = function(a) {
return this.filter(function(i) {
return a.indexOf(i) >= 0;
});
};
alert([1,2,3,4,5].common([4,5,6])); // "4, 5"
Again as you mention in your post, this logic also works by taking each element and checking whether it exists in the other.
A hair more efficient way is convert one of the arrays into a hash table and then loop through the second one, checking the presence of elements at O(1) time:
a = [1,2,3,4,5]
b = [1,7,3,8,5]
map = {}
a.forEach(function(x) { map[x] = 1 })
intersection = b.filter(function(x) { return map[x] === 1 })
document.write(JSON.stringify(intersection))
This only works if elements in question are primitives. For arrays of objects you have to resort to the indexOf method.
ES6 ("Harmony") does support Set, but strangely not set operations (union, intersection etc), so these should be coded by hand:
// Firefox only
a = [1,2,3,4,5]
b = [1,7,3,8,5]
sa = new Set(a)
sb = new Set(b)
sa.forEach(function(x) {
if (!sb.has(x))
sa.delete(x);
});
document.write(uneval([...sa]))
JavaScript's arrays don't have a method that does intersections. Various libraries provide methods to do it (by looping the array as you describe), including Underscore and PrototypeJS (and others, I'm sure).

Where can I find a List class for javascript with add() remove() and contains()?

Where can I find a List class for javascript with add(obj) remove(obj) and contains(obj)?
you can already use push instead of add and pop instead of remove.
How do I check if an array includes an object in JavaScript? contains an answer for how to do contains.
You could write some simple array extensions:
Array.prototype.add = function (obj) {
if (this && this.length)
this.push(obj);
};
[1, 2, 3].add(4);
... etc
Those aren't hard features to implement. I would simply create my own custom type that inherited from Array and added the two additional methods you'd like (since you can already use push to add items).
You can just use the native javascript's arrays
var arr = [];
arr.push(5); // add(obj)
arr.indexOf(5); // returns the index in the array or -1 if not found -> contains(obj)
For removing, you can use arr.pop() to remove last element or arr.shift() to remove the first element.
More on javascript's arrays - http://www.hunlock.com/blogs/Mastering_Javascript_Arrays

Categories

Resources