Mapping multiple keys to the same value in a Javascript hash - javascript

I use a Javascript hash object to store a set of numerical counters, set up like this [this is greatly simplified]:
var myHash = {
A: 0,
B: 0,
C: 0
};
Is there a way to make other keys, ones not explicitly in myHash, map to keys that are? For instance, I'd like [again, this is simplified]:
myHash['A_prime']++; // or myHash.A_prime++;
to be exactly equivalent to
myHash['A']++; // or myHash.A++;
e.g. incrementing the value found at the key A, not A_prime.

Assuming there aren't any valid string values in this hash, you could create your own mapping of keys to other keys, within the hash itself, and wrap the key/value pairs in your own function, as follows:
var hash = {
A: 0,
B: 0,
C: 0,
A_asdf: 'A',
B_asdf: 'B',
A_another: 'A'
}
function increment(key)
{
// iteratively find the real key
while (typeof(hash[key]) == 'string')
{
key = hash[key];
}
hash[key]++;
}

A way of solving this would be wrapping all values in an object, and use this object in several keys.
var myHash = {
A: {value: 0},
...
};
myHash['A_prime'] = myHash['A'];
myHash['A_prime'].value++;

I think you would be better off just writing a function to accomplish the incrementation of one hash array or multiple depending on what you are trying to accomplish. I may have not understood the question correctly but this is my solution.
var smallHash = {
A: 0,
B: 0,
C: 0,
A_prime:'A',
B_prime:'B',
C_prime:'C'
};
function incrementPrime(myHash,key)
{
letterKey = myHash[key];
myHash[letterKey]++;
}
incrementPrime(smallHash,'C_prime');
alert("C is now: "+smallHash['C']); // should return 1

You could act on the key, instead of the hash:
var myHash = {
A: 0,
B: 0,
C: 0
};
function incr(prop){
myHash[prop[0]]++;
}
incr('A');
incr('A_asdf');
The function incr could be anything else you want to apply to the hash.

As described, no. If you can change your keys to objects though you'd get closer:
var x = new Object();
var y = x;
myHash[x] = 1;
myHash[y]++; // should increment the value since y is x.

Related

Javascript map with composite keys

In JavaScript I want to store values to compound keys, similar to a C# dictionary with a tuple as key. This is where I came across the Map class. However, it does not seem to work quite as well as I would like it to. Here's my current approach:
var test = new Map();
test.set({a: 1, b: 1}, 'Bla');
test.set({a: 5, b: 7}, 'Blub');
test.get({a: 1, b: 1}); // ==> Returns undefined; would expect 'Bla'
I guess, that this has something to do that both objects with {a: 1, b: 1} have a different memory address and therefore are the same, but not identical. The Dictionary class in c# uses a hash function in background. Is there something similar in JS? Or a much easier approach?
My real key object consistst of three strings.
Your analysis is correct. It works like this because in Javascript you usually operate primitive objects that don't have all this hashing behavior attached to them out of the box. Nothing stops you from implementing your own Dictionary with hash function in background though
class Dictionary {
map = {}
constructor(hashFunction) {
this.hashFunction = hashFunction
}
set(key, item) {
this.map[this.hashFunction(key)] = item
}
get(key) {
return this.map[this.hashFunction(key)]
}
delete(key) {
delete this.map[this.hashFunction(key)]
}
}
const dict = new Dictionary((keyObject) => JSON.stringify(keyObject))
dict.set({ a: 1, b: 2 }, 'hello')
console.log(dict.get({ a: 1, b: 2 })) // hello
As to what to use, Map or object, the difference between Map and object is simply that object only supports string keys (also Symbols but irrelevant right now) while Map supports any value at a cost of using more resources, less compatibility with old browsers, and it's generally less handy to use than object (and also stops GC from cleaning out those objects you use as keys). That said, object is your choice here
{} this operator will create a new object every time; and a new object will have a different object refenece each time; if you save the object reference and use that for multiple operation its ok; but since you are trying to use a new object refence every time it won't work; you may either use a primitive type as key, or same object reference like the snippet below
//approach 1 using same object reference
var test = new Map();
var obj = {a: 1, b: 1};
test.set(obj, 'Bla');
test.set({a: 5, b: 7}, 'Blub');
let result = test.get(obj);
console.log(result);
// aproach 2 using JSON.stringify
test = new Map();
test.set(JSON.stringify({a: 1, b: 1}), 'Bla');
test.set({a: 5, b: 7}, 'Blub');
result = test.get(JSON.stringify({a: 1, b: 1}));
console.log(result)

Update an object with matching properties and ignore new properties

I'm using Typescript and I would like to update an object with another, only on the matching keys.
// Destination
objectOne = {
a: 0,
b: 0,
};
// Source
objectTwo = {
a: 1,
b: 1,
c: 1,
};
// Expected
result = {
a: 1,
b: 1,
};
// Current solution
const current = {};
Object.keys(objectTwo).forEach(key => key in objectOne ? current[key] = objectTwo[key] : null);
console.log(current);
is there a one-liner (i.e. not a custom function that iterates over the keys) that would ignore the property c in the source ? I would also like to avoid using libraries such as lodash or JQuery.
Duplicate EDIT my question isn't about merging two objects, my question is about ignoring the fields in the second object, that aren't in the first object.
After a while without answers, it seems the shortest solution is the one I provided myself :
Object.keys(newObj).forEach(key => key in oldObj? result[key] = newObj[key] : null)
const result = Object.keys(objectOne)
.reduce((init, key) => Object.assign(init, {[key]: objectTwo[key]}) , {});
I think there is no built-in function to accomplish what you need, rather than a custom one with iterating over keys of the first object and values of the second one:
const objectOne = {
a: 0,
b: 0
};
const objectTwo = {
a: 1,
b: 1,
c: 1,
};
const result = Object.keys(objectOne).reduce((all, key) => {
all[key] = objectTwo[key] || objectOne[key];
return all;
},{});
console.log(result);

How do I print an object value by inputting the object key into the function parameter?

How do I print an object value by inputting the object key into the function parameter?
var z = {a: 1, b: 2, c: 3};
var list = function(x){
console.log(z.x);
};
For example if I input list(a) I would like the function to read it as console.log(z.a), and therefore output = 1
Pass an argument as a string and use square brackets instead of ..
var z = {a: 1, b: 2, c: 3};
var list = function(x){
console.log(z[x]);
};
list('a')
Here you go:
z[a]
...
list('a')
Change the dot to an index and put a in quotation marks

How to compare two JSON values based on the key name in javascript?

I have two JSON arrays like
array1=[{a:1,b:2,c:3,d:4}]
&
array2=[{a:2,b:5,c:3,d:4}]
Is there any method to find the value of one of the keys in array1 present in array 2.Here in the array 1 key b contains the value 2,and array2 also contain a key a with value 2. How can I capture the key name of array 2 which has the same value for one of the keys in array.
I don't quite understand if you are interested in operating on arrays or objects - as your example is a pair of single element arrays, and the comparison is clearly between the objects in the arrays.
That said, if your goal is to compare two objects, and return the set of keys that are the same for both, you would do something like
obj1 = {a:1,b:2,c:3,d:4};
obj2 = {a:2,b:5,c:3,d:4};
function sameKeys(a,b) {
return Object.keys(a).filter(function(key) {
return a[key] === b[key];
});
}
console.log(sameKeys(obj1, obj2));
When I run this, I get:
[ 'c', 'd' ]
I hope that is what you were asking...
Wrote a prototype function to compare an object against another.
var obj1 = {a: 1, b: 2, c: 3, d: 4};
var obj2 = {a: 2, b: 4, c: 100, d: 200}
Object.prototype.propertiesOf = function(visitorObj) {
result = {};
//Go through the host object
for (thisKey in this) {
//Exclude this function
if (!this.hasOwnProperty(thisKey))
continue;
//Compare the visitor object against the current property
for (visitorKey in visitorObj) {
if (visitorObj[visitorKey] === this[thisKey])
result[visitorKey] = thisKey;
}
}
return result;
}
console.log(obj1.propertiesOf(obj2));
Simply call the propertiesOf function of any object by passing another object as the argument. It returns an object which has similar keys linked to each other.
The above example will result in:
{a: "b", b: "d"}
It seems you want something like this: make a function that finds all the keys in the 2nd object that have a given value. Then pass the value from the first object to that function.
obj1={a:1,b:2,c:3,d:4};
obj2={a:2,b:5,c:3,d:4};
function findKeysByValue(obj, v) {
var results = [];
for (var k in obj) {
if (obj.hasOwnProperty(k) && v == obj[k]) {
results.push(k);
}
}
return results;
}
console.log(findKeysByValue(obj2, obj1['b'])); // ['a']

Javascript - push into JSON array

Just trying to update a JSON array and hoping for some guidance.
var updatedData = { updatedValues: [{a:0,b:0}]};
updatedData.updatedValues.push({c:0});
That will give me:
{updatedValues: [{a: 0, b: 0}, {c: 0}]}
How can I make it so that "c" is part of that original array?
So I end up with {a: 0, b: 0, c: 0} in updatedValues?
You actually have an object inside your array.
updatedData.updatedValues[0].c = 0;
will result in your desired outcome.
The updatedValues is a plain object and you have to add c as property.
var updatedData = { updatedValues: [{a:0,b:0}]};
updatedData.updatedValues[0]["c"] = 0;
If you are using jquery then do as follows.
var updatedData = { updatedValues: [{a:0,b:0}]};
$.extend(updatedData.updatedValues[0],{c:0});
You're pushing something to the updated values array, rather than setting an attribute on the 0th element of the array.
updatedData.updatedValues[0].c = 0;
You can add an item in the object.
This should work.
updatedData.updatedValues[0]['c']=0;

Categories

Resources