Using Javascript object as object key - javascript

I am trying to devise a way to use a simple Javascript object (one level deep key value pairs) as a key to another object. I am aware that merely using the object without stringification will result in [Object object] being used as the key; see the following: Using an object as a property key in JavaScript (so this question is not a duplicate).
There is a blog post about it that takes this into account and also accounts for the need to sort by object key since their order is not guaranteed, but the included Javascript code runs over a 100 lines. We are using the underscore.js library since that goes hand in hand with backbone but pure Javascript alternatives will also be of interest.

In ECMAScript 6 you'll be able to use Maps.
var map = new Map();
var keyObj = { a: "b" },
keyFunc = function(){},
keyString = "foobar";
// setting the values
map.set(keyObj, "value associated with keyObj");
map.set(keyFunc, "value associated with keyFunc");
map.set(keyString, "value associated with 'foobar'");
console.log(map.size); // 3
// getting the values
console.log(map.get(keyObj)); // "value associated with keyObj"
console.log(map.get(keyFunc)); // "value associated with keyFunc"
console.log(map.get(keyString)); // "value associated with 'a string'"
console.log(map.get({ a: "b" })); // undefined, because keyObj !== { a: "b" }
console.log(map.get(function(){})); // undefined, because keyFunc !== function(){}
console.log(map.get("foobar")); // "value associated with 'foobar'"
// because keyString === 'foobar'

I wrote a hash table implementation that accepts arbitrary keys but I suspect you'll reject it on the grounds of the relatively large file size.
https://code.google.com/p/jshashtable/

Here is an underscore based solution that relies on first converting the object to key-value pairs.
var myObj = { name: 'john', state: 'ny', age: 12};
var objPairs = _.pairs(myObj);
var sortedPairs = _.reduce(_.keys(myObj).sort(), function(sortedPairs, key) {
var pair = _.find(objPairs, function(kvPair) {return kvPair[0] == key});
sortedPairs.push(pair);
return sortedPairs;
}, []);
console.log(JSON.stringify(sortedPairs)); //stringifying makes suitable as object key
// [["age",12],["name","john"],["state","ny"]]

You could use a pattern like this. This way, your key for an object is this random id that you generate for every object.
var MyObject = function(name) {
this.name = name;
this.id = Math.random().toString(36).slice(2);
}
MyObject.prototype.toString = function() {
return this.id;
}

Related

Implement "like" HashMap in js with <string, object>

I develop an app with react and node js.
I have a JSON file that stores all user objects with some properties (first name, last name, email, ... )
I want to implement "like" hashmap with key, value.
the key is a string for the email and value will be all the user object
like (in java):
HashMap< string, User >
I want this to access fast for a user object, search by email (the key) on server-side (NodeJS)
What is a good way to implement something like this?
Thanks!
What about a simple object in Javascript?
All objects in Javascript can be accessed by the Array-like convention.
For example, you can create an object like this:
const Users = {}
Users['admin#admin.com']=userObject;
Users['test#test.com']=user2Object;
ect..
If you are going to work with modern browser/node versions, consider using a Map
Example from the link above:
let myMap = new Map()
let keyString = 'a string'
let keyObj = {}
let keyFunc = function() {}
// setting the values
myMap.set(keyString, "value associated with 'a string'")
myMap.set(keyObj, 'value associated with keyObj')
myMap.set(keyFunc, 'value associated with keyFunc')
myMap.size // 3
// getting the values
myMap.get(keyString) // "value associated with 'a string'"
myMap.get(keyObj) // "value associated with keyObj"
myMap.get(keyFunc) // "value associated with keyFunc"
myMap.get('a string') // "value associated with 'a string'"
// because keyString === 'a string'
myMap.get({}) // undefined, because keyObj !== {}
myMap.get(function() {}) // undefined, because keyFunc !== function () {}

How to set dynamic properties on object in Javascript?

Dynamically I'm getting several objects having the following structure.
obj1 = {
prop: 'one',
key: 'string',
value: 2
}
obj2 = {
prop: 'one',
key: 'diffString',
value: 3
}
Also, I have an object which I want to turn into this using received objects.
mainObject = {
prop: {
key1: value,
key2: value
}
}
I'm trying to use this
mainObject[obj.prop][obj.key] = obj.value;
But it gives me an error because at this point mainObject is just an empty object and it doesn't have mainObject[obj.prop]
Any help will be much appreciated.
The simplest way to achieve this is as follows:
// If no value for obj.prop exists, assign empty object
mainObject[obj.prop] = mainObject[obj.prop] || {};
// Assign value to obj.key of object at mainObject[obj.prop]
mainObject[obj.prop][obj.key] = obj.value;
This code is first ensuring that a valid value (object) exists at the key obj.prop on mainObject. If there is not valid object at key obj.prop, then a new empty object is assigned {}.
The mainObject[obj.prop][obj.key] = obj.value assignment can now be performed safely seeing that an object exists at mainObject[obj.prop].
Alternatively, if you want a more concise way of doing this you could consider the lodash library which offers the .set() method:
_.set(mainObject, obj.prop + '.' + obj.prop, obj.value);
Hope this helps!
all you can do is push your upcoming object into an array and by using reduce method you can simply achieve your desired output
let mainObject = [obj1, obj2].reduce((result, obj) => {
result[obj.prop] = result[obj.prop] || {};
result[obj.prop][obj.key] = obj.value;
return result;
}, {});

Javascript reserved word and object

I'm making a dictionary of words, so there are 1,000,000+ words.
The problem comes when I need to store the word constructor. I know this is a reserved word in javascript, but I need to add it to the dictionary.
var dictionary = {}
console.log(dictionary ['word_1'])
//undefined, this is good
console.log(dictionary ['word_2'])
//undefined, this is good
console.log(dictionary ['constructor'])
//[Function: Object]
// this cause initialization code to break
How can I fix this? I could muck with the it like key=key+"_" but that seems bad. Is there anything else I can do?
Instead of using a JS object, you could use the built-in Map type which uses strings/symbols as keys and does not conflict with any existing properties.
Replace
var dictionary = {} with var dictionary = new Map()
Override the constructor key as undefined
According to the MDN Object.prototype page, the only thing that isn't hidden by the __fieldname__ schema is the "constructor field". Thus, you could just initialize your objects via { 'constructor': undefined }.
However, you would have to make sure that in your for .. in statements would filter out all keys with undefined as their value, as it would pick up constructor as a "valid" key (even though it wouldn't before you specifically set it to undefined). I.E.
for(var key in obj) if(obj[key] !== undefined) { /* do things */ }
Check for types when getting/setting
Otherwise, you could just check the type when you 'fetch' or 'store' it. I.E.
function get(obj, key) {
if(typeof obj[key] !== 'function') // optionally, `&& typeof obj[key] !== 'object')`
return obj[key];
else
return undefined;
}
I think you should store all words and translation of them in an array. When you need to translate a word, you can use find method of Array.
For example:
var dict = [
{ word: "abc", translated: "xyz" },
...
];
Then:
var searching_word = "abc";
var translation = dict.find(function (item) {
return item.word == searching_word;
});
console.log(translation.translated);
// --> xyz
To achieve expected result , use below option of using index to get value of any key value
var dictionary = {};
var dictionary1 = {
constructor: "test"
};
//simple function to get key value using index
function getVal(obj, val) {
var keys = Object.keys(obj);
var index = keys.indexOf(val);//get index of key, in our case -contructor
return obj[keys[index]]; // return value using indec of that key
}
console.log(getVal(dictionary, "constructor"));//undefined as expected
console.log(getVal(dictionary1, "constructor"));//test
console.log(dictionary["word_1"]);
//undefined, this is good
console.log(dictionary["word_2"]);
//undefined, this is good
codepen - https://codepen.io/nagasai/pen/LOEGxM
For testing , I gave one object with key-constructor and other object without constructor.
Basically I am getting the index of key first and getting value using index

Using object as ES2015 map key

I've been trying to get a hold of ES2015 map concept and one thing I don't understand is the following:
var mapRawObj = new Map();
var rawObj = {j:"I like penguin"};
mapRawObj.set(rawObj,true);
console.log(mapRawObj.get(rawObj)); //this outputs true
mapRawObj.set({j:"I like polar bear"},true);
console.log(mapRawObj.get({j:"I like polar bear"})); //this outputs undefined
The first one works, the second one doesn't, and I don't understand why?
I thought when you register object as key, it's the object itself, not the object's name. That's why in the below example when you re-assign the key object, it fails as key?
var obj = { a:"hello ", b:"world "};
var mapObj = new Map();
mapObj.set(obj,true);
obj = {d:34}; //obj is re-assigned
console.log(mapObj.get(obj)); // outputs undefined
Objects with the same data are not equal in Javascript, ie
{ hello: 'world'} === { hello: 'world'} // false
The first example uses the same object as the key for set and get, so the key is identical:
var obj = { hello: 'world'};
obj === obj // true
But the second example creates a new object for the get(), which is not identical to the key used to set the value in the map. Since it's not identical, the map doesn't have anything set against this new key and returns undefined.
Even though the new key has exactly the same data as the original key, the objects aren't referring to the same data internally.
More on object equality

Does Javascript have associative arrays?

Does Javascript have associative arrays? Please explain.
Nope; JavaScript arrays are just numeric keys and mixed values. The same thing can be achieved (or, actually, it's exactly the same as associative arrays in other languages) with objects:
var foo = {
a: 123,
b: 'CDE'
};
foo.a; // 123
foo['a']; // 123
You could use arrays:
var foo = [];
foo.a = 123;
foo.b = 'CDE';
foo.b; // CDE
foo['b']; // CDE
HOWEVER, this should never be done because this will not enter the key/value pairs into the array, but add them to the array object as properties. (besides, {a: 123} is easier than a = []; a.a = 123) If you need key/value pairs, use Objects. If you need an enumerated list, use arrays.
This answer is pretty much a copy-paste of my previous answer on this question.
The situation has changed in the five years since this question was asked.
Due to weak typing associative arrays can be faked in JavaScript:
>> var names = new Array();
undefined
>> names["first"] = "Dotan";
"Dotan"
>> names["last"] = "Cohen";
"Cohen"
>> for ( key in names ) { console.log(key+" "+names[key]) }
undefined
first Dotan
last Cohen
That is sometimes useful, and all browsers released since 2012 support it, but there are caveats! The array cannot be simply read back:
>> names
Array [ ]
More importantly, the array's length cannot be easily retrieved:
>> names.length
0
Therefore this is not an associative array in the sense that JavaScript would have supported it had it been intended, but rather a workaround that is often useful if for whatever reason a real JS object does not support what you need:
>> var names = {};
undefined
>> names.first = "Dotan";
"Dotan"
>> names.last = "Cohen";
"Cohen"
>> for ( key in names ) { console.log(key+" "+names[key]) }
undefined
first Dotan
last Cohen
>> names
Object { first: "Dotan", last: "Cohen" }
>> Object.keys(names).length
2
The closest we have is an object; the easiest way you can define this is using object literal syntax.
var assocArray = {
key: 1,
key2: 2
};
You should be wary of a few things however:
It does not have a .length property.
You should use for in to iterative over it, rather than for(;;;);, but should combine it with hasOwnProperty():
for (var x in assocArray) {
if (assocArray.hasOwnProperty(x)) {
// x = the key, assocArray[x] = the value
}
}
There is no concept of ordering/ sorting the members. Whilst all implementations I know of iterate the members in the order they were added, this is not standardised.
Instead of associative arrays. Javascript has objects. Properties of an object are addressed using a string.
var obj1 = {}; // declare empty object
var obj2 = {a: 1, b: 'string', c: [4,5]}; // obj with 3 properties, a, b, and c
// note that the 'c' property contains an anonymous array
alert(obj2.a); // shows 1
obj2.a = 'another string'; // redefine the 'a' property
obj2.cookie = 'oatmeal'; // add a new property to the object
obj2['ice_cream'] = {vendor: 'Beyers',
flavor: 'Chocolate Surprise'}; // add anonymous object as
// a new property for the object
assert(obj2.a === obj2['a']); // two ways to retrieve the value
var i = 'a'; // using an index varable
assert(obj2.a === obj2[i]); // note the i does not have apostrophes around it
See the Quirksmode docs
Something comparable in JavaScript is an object.
var my_obj = { key : 'value' }
Sure it does (kind of, use objects)
var foo = {
bar: "hello"
}
accessible with
foo.bar

Categories

Resources