How to get object from array by object's unique property value? - javascript

Basically everything is said with the title: how to get the object from array by object's property value which is unique by the way?
Situation:
My current strategy is that I gave id attribute to the div of that object's property id (all ids are unique, take a look at Array of objects below) which looks like this:
<div id="3590" class="my-div"></div>
Now, when this div is clicked, I'll get the id attribute and I need to find the right object because I also need to get some other properties and also make some changes to some properties.
Why Im doing this:
This seems to be the only way because as I was told in other question that there's no way to access the object, even when this div is one of the object's properties (take a look at Array of objects below).
If that's not true, please let me know. This is super important!
Array of objects:
0: myObject
__e3_: Object
div: div#3590.my-div
gm_accessors_: Object
gm_bindings_: Object
id: 3590
latlng: _.K
map: _.ng
uh: Object
__proto__: c
1: myObject
__e3_: Object
div: div#3591.my-div
gm_accessors_: Object
gm_bindings_: Object
id: 3591
latlng: _.K
map: _.ng
uh: Object
__proto__: c
//thousands of objects
There can be thousands of objects in that array and that's why I added word "fastest" to the question: Im concerned about the performance because there's also other stuff going on.
Also, I prefer vanilla JS because Im currently learning it but if you know a good and fast way in jQuery, please go ahead, I'll convert it myself.
More details:
Objects are in array because I also need to iterate them (more often than working with them one-by-one)
All one-by-one actions are done via click events (user triggered and there's some protection: only one action at a time)

Keep reference to the corresponding object in the element as well.
So, whenever you click an element, the element object itself will have the reference to corresponding object. No need to find from the array.
And yes please be careful with name collisions. Assign object to new key so that object doesn't replace value of element object's existing key.
For old browsers, I am not sure they can even render thousands of elements.
Example:
var element = document.createElement("div");
element.myObj = {id: 3306, name: 'coolBoy'}; //make sure key, 'myObj' in this case, doesn't already exist.
var myArray = [];
myArray.push(element.myObj); //if you need to keep in array as well.
element.onclick = function(e){
console.log(e.currentTarget.myObj.name);
};

I'd recommend using a Map collection - it allows for both fast iteration and fast access by key, and is a builtin data structure.
If you don't want to go down the ES6 route (and not use a shim either), a reasonably fast approach would be to keep the array sorted. You can use binary search to access single elements.
Notice that for a thousand objects, there probably won't be an observable difference anyway. Don't prematurely optimise. Just keep your API to access the collection clean so that you can easily swap out the data structure in the future, should there be any need.

function getObjectFromId(id) {
return ARR.filter(function (obj) {
return obj.id === id;
})[0];
}

Related

Method to track references to each javascript object from all other objects?

I am interested in using vanilla Javascript objects and arrays to model data that has the data structure of a connected directed graph. One way to do this would be to use multiple object references within a single object tree to represent distinct edges of the graph. However, to use this efficiently, there needs to be a way to easily check what are the incoming edges to a given object (or put another way, for each object to know what all of it's parents are, and to know the property keys from each parent to itself.)
According to this older Stack Overflow post there is no built-in way to do this in Javascript: Get all object references in Javascript.
I've started making my own library called Parent Aware Objects that uses Proxy objects to intercept basic object assignment operations in order to keep track all the references to each object.
Before I go too far down this path, I wanted to ask if there might be an easier way to accomplish this.
This is the functionality I want:
const fido = {
name: 'Fido'
};
const alan = {
name: 'Alan',
pet: fido
}
const sarah = {
name: 'Sarah',
dogWalkerFor: fido
}
getParents(fido)
The function call getParents(fido) should return a list of entries that contains the alan object with key "pet" and sarah object with key "dogWalkerFor".
You would need a collection of all the nodes in the graph to search for:
const graphNodes = [fido, alan, sarah];
Then you can easily get all nodes that reference Fido:
graphNodes.filter(node => Object.values(node).includes(fido))
Of course, searching the entire graph every time is not really efficient. To do that, you would need to store the backedges on the node itself, or in a Map or something where you can easily look them up. This would then require updating that data structure every time you update your graph.

JavaScript assoziativ array :/

what's the best way in JavaScript to store values in an assoziative array? I tried a lot of things and it always brakes somehow.
I tried something like:
var test = [];
for(var prop in json) {
test[prop] = json[key];
}
this works and i get a cool array then i can actually use. However calling test.length gives me 3 when there should be 10 items, it sometimes gives me 0 when there should be at least 8 items.
What do i do wrong? What's the best way to go here to get an assoziative array going which i can use properly like in Java?
Everything is an object in JavaScript. foo['bar'] is the same as foo.bar. Array is just an object with some predefined methods that let it emulate what you would call a numeric array in PHP or just an array in almost any other language. JavaScript objects work like associative arrays in PHP. The general non-PHP name for it is hash.
So, to address your problem with length, it is a predefined property of an array object. Using it on an object that isn't an array will not give you the results you are expecting. To count the number of properties in an object, you can use
Object.keys(obj).length
in modern browsers. keys() function gets an array of keys from a hash, so it will have a correct length property.
If you wish to support older browsers, you have to iterate through object properties and count them manually. Be aware that for (var prop in json) will also iterate through the properties of every object in the prototype chain, so you might want to check if a property is object's own property using hasOwnProperty() method.

Saving an element as a index in a object

I'd like to save a DOM element in a object. But not as a value, i want save it as a key of the object. But i think the core of javascript is not able to do that.
data={}
data[$('div#a')] = 'A';
data[$('div#b')] = 'B';
console.log(data[$('div#a')]); //return B
Do you know some way to save the element in a index object?
Imagine i have XXXXXX elements on my document. If i want to access to the element properties when some event happen on it i dont want to iterate XXXXXX elements to find it.
Why i don't use data of jquery for two reasons:
I want to do it on native javascript
I dont want another array to iterate separate data from the elementid
So the perfect way to do it was have only one object with the elements on the key to acces them easy. And if i want iterate them i only have to do for i in data
JavaScript objects will only accept strings as keys, and JS will use .toString() if you try to use anything else as a key, typically resulting in everything being stored under the (single) key "[object Object]".
Is there any reason you can't use $('#a').data() to store the data associated with that element directly on the element?
Failing that, assuming that every such element has an ID, just use the element ID as the object key.
NB: ES6 has a Map object which can use arbitrary keys, but that's only an experimental feature in current browsers. However even then you would have to use the actual element as the key rather than a jQuery wrapped $(element) object, since $('#a') !== $('#a') - you would have to use the exact same original jQuery object each time you access the map, not a newly constructed object.
Javascript objects only accept string as key.
So if you try to give key value other than string, javascript will internally call .toString() method of that object and use return value of it as key.
Object keys have to be stings.
You can use the data method to associate anything to the element:
$('div#a').data('name', 'A');
$('div#b').data('name', 'B');
console.log($('div#a').data('name')); //return B

How can you reference a custom data structure as if it were an array? [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Javascript custom index accessor
If I were to write, say, a doubly-linked list object in Javascript, is there a way to reference this new list in a fashion like an array?
For instance, if I wanted the value of node 5, I'd like to query
newLinkedList[5]
instead of doing what I've been doing, which is something like
newLinkedList.getNode(5)
Basically, is there a way to "pretty up" references to custom data structures, or do you have to do it as a custom function each time?
Arrays in Javascript are really just objects with special handling for numerical properties. You can accomplish the same thing yourself, but currently Javascript doesn't provide a simple mechanism for transparent two-way accessing of those indices; you'll have to handle adding and deleting objects with named methods, but you can still benefit from reading them with array-like indexing.
Here's an example of a simple custom "Arrayish" object:
var ll_array = {};
ll_array.length = 0;
ll_array.addNode = function (newNode) {
this[this.length] = newNode;
this.length++;
};
ll_array.addNode('Foo');
ll_array.addNode('Bar');
console.log('Length: ' + ll_array.length);
console.log(ll_array);
console.log(ll_array[0]);
​
http://jsfiddle.net/rbmsJ/1/
The brute force method of traversing the list, then assigning each item in the traversal to an array element, is the first thing that comes to mind:
Pretend you have a LinkedList object. Let's also presume there are methods for iterating the list called Head, and Next. Now, caveat being that this is entirely untested, you could create a prototype toArray() method in a manner such as:
LinkedList.prototype.toArray() = function () { var array={};
var currentItem = list.head;
while (currentItem!=null){
array.addNode(currentItem);
currentItem=currentItem.Next;
}
return array;
}
Obviously this must allow for other presumed functions, but the idea is to traverse the linked list, and put a reference to each element in an array, and return it. Hope that helps in some way.
From your question:
objects are saved in a double-linked list.
you know the getNode(int n) method to get n-th element.
there are no way to allow you get the n-th element with array style, [n]. because linked lists are not arrays, the elements in a linked list are linked to each other, this data structure is different from ordinary array or JavaScript style array:named property.
Arrays ARE double linked lists without the links. To traverse right you simply increment the index, to traverse left you decrement the index.
You could write yourself a set of functions to perform the basic list operations and still have the facility of using simple indexing to reach any aribtrary element.

Can a DOM object be an index/key in Javascript array?

Would like to maintain a map/hash of DOM objects. Can they serve as key objects? If not, what are the alternatives, please? If there are better ways - kindly enlist them as well.
You can put anything as the key, but before actual use it is always converted to string, and that string is used as a key.
So, if you look at what domObject.toString() produces, you see it is not a good candidate. If all of your dom objects have an id, you could use that id.
If not, and you still desperately need a key based on DOM object, you probably could do with using, for example, _counter attribute with automatic counter in background putting new unique value in a DOM object if _counter is not yet present.
window already maintains all DOM objects as properties. Instead of putting your own keys for each 'DOM object' try to use window or document object and methods that uses index based on the layout of DOM tree.
No, because object keys are strings.
You'd have to "serialise" your objects by id or something, then perform a lookup later. Probably not worth it, depending on what your actual goal is here.
No, but you can set an attribute on the DOM element that contains a number, which you would have as the index in a numerically-indexed array.
Easiest is to set a data-attribute on the element instead.
Not exact. But I think you want something like below. You can do with jquery,
The .serializeArray() method creates a JavaScript array of objects, ready to be encoded as a JSON string. It operates on a jQuery object representing a set of form elements. The form elements can be of several types
Refer below link :
http://api.jquery.com/serializeArray/

Categories