How do I merge two dictionaries in Javascript? [duplicate] - javascript

This question already has answers here:
How can I merge properties of two JavaScript objects dynamically?
(69 answers)
Closed 1 year ago.
var a = {};
a['fruit'] = "apple";
var b = {};
b['vegetable'] = "carrot";
var food = {};
The output variable 'food' must include both key-value pairs.

You could use Object.assign.
var a = { fruit: "apple" },
b = { vegetable: "carrot" },
food = Object.assign({}, a, b);
console.log(food);
For browser without supporting Object.assign, you could iterate the properties and assign the values manually.
var a = { fruit: "apple" },
b = { vegetable: "carrot" },
food = [a, b].reduce(function (r, o) {
Object.keys(o).forEach(function (k) { r[k] = o[k]; });
return r;
}, {});
console.log(food);

Ways to achieve :
1. Using JavaScript Object.assign() method.
var a = {};
a['fruit'] = "apple";
var b = {};
b['vegetable'] = "carrot";
var food = Object.assign({}, a, b);
console.log(food);
2. Using custom function.
var a = {};
a['fruit'] = "apple";
var b = {};
b['vegetable'] = "carrot";
function createObj(obj1, obj2){
var food = {};
for (var i in obj1) {
food[i] = obj1[i];
}
for (var j in obj2) {
food[j] = obj2[j];
}
return food;
};
var res = createObj(a, b);
console.log(res);
3. Using ES6 Spread operator.
let a = {};
a['fruit'] = "apple";
let b = {};
b['vegetable'] = "carrot";
let food = {...a,...b}
console.log(food)

You could use the spread operator in es6, but you would need to use babel to transpile the code to be cross browser friendly.
const a = {};
a['fruit'] = "apple";
const b = {};
b['vegetable'] = "carrot";
const food = { ...a, ...b }
console.log(food)

Create a Utility function which can extend Objects, like:
function extendObj(obj1, obj2){
for (var key in obj2){
if(obj2.hasOwnProperty(key)){
obj1[key] = obj2[key];
}
}
return obj1;
}
And then extend this food object with the another Objects. Here is example:
food = extendObj(food, a);
food = extendObj(food, b);

Related

how to merge two array objects in javascript

Just wondering what is my best approach to merge these two arrays together.
example
var a = [{"ID":11021,"ASSET_NAME":"panda","SERVICE_NAME":"Open Ticket"}]
var b = [{"ID":11021,"ASSET_NAME":"panda","SERVICE_NAME":"open requests"}]
Looking to merge them into:
var c = ["ID":11021, ASSET_NAME:"panda", service_name: ['open requests','open tickets']]
any help would be great.
Thanks
You can use one object to store ID's and reduce() to create new array of merged objects.
var a = [{"ID":11021,"ASSET_NAME":"panda","SERVICE_NAME":"Open Ticket"}]
var b = [{"ID":11021,"ASSET_NAME":"panda","SERVICE_NAME":"open requests"}]
var obj = {}
var result = a.concat(b).reduce(function(r, e) {
if (!obj[e.ID]) {
obj[e.ID] = {
ID: e.ID,
ASSET_NAME: e.ASSET_NAME,
service_name: []
}
r.push(obj[e.ID])
}
obj[e.ID].service_name.push(e.SERVICE_NAME)
return r
}, [])
console.log(JSON.stringify(result, 0, 4))
You can utilize the map method of arrays, like so:
var a = [{'eprid':112}, {'asset_name':'panda'}, {'service_name': 'open tickets'}];
var b = [{'eprid':112}, {'asset_name':'panda'}, {'service_name': 'open requests'}];
var c = a.map((obj, i) => {
for (key in obj) {
if(obj[key] !== b[i][key]) {
obj[key] = [obj[key], b[i][key]]
}
return obj;
}
})
console.log(c) // [{'eprid':112}, {'asset_name':'panda'}, {'service_name': ['open ticket', 'open requests']}]

convert array to object javascript

I have the following array:
["recordList", "userList", "lastChanged"]
And I want something like this:
lastChangedValue = "231231443234";
var object = {};
object = {
recordList: {
userList: {
lastChanged: lastChangedValue
}
}
}
How I can do this?
Thanks in advance.
Try this:
var array = ["recordList", "userList", "lastChanged"];
var value = "231231443234";
function arrayToObject(array, object, value) {
var ref = object;
for (var i=0; i<array.length-1; ++i) {
if (!ref[array[i]]) {
ref[array[i]] = {};
}
ref = ref[array[i]]
}
ref[array[array.length-1]] = value;
return object;
}
alert(JSON.stringify(arrayToObject(array, {}, value)));
You can iterate through property names and create one nested level of new object in each iteration:
var props = ["recordList", "userList", "lastChanged"];
var lastChangedValue = "231231443234";
var obj = {}
var nested = obj;
props.forEach(function(o, i) {
nested[o] = i === props.length - 1 ? lastChangedValue : {};
nested = nested[o];
});
console.log(obj);
There are probably a bunch of ways to do it, one way is with reduce
var keys = ["recordList", "userList", "lastChanged"];
var temp = keys.slice().reverse(),
lastChangedValue = "231231443234";
var result = temp.reduce( function (obj, val, ind, arr) {
if (ind===0) {
obj[val] = lastChangedValue;
return obj;
} else {
var x = {};
x[val] = obj;
return x;
}
}, {});
console.log(result);
Solving with recursion
var fields = ["recordList", "userList", "lastChanged"];
lastChangedValue = "231231443234";
var object = {};
(function addFields(o, i, v) {
if (i == fields.length - 1) {
o[fields[i]] = v;
return;
}
o[fields[i]] = {};
addFields(o[fields[i]], ++i, v)
})(object, 0, lastChangedValue);
alert(JSON.stringify(object));

Swapping two properties of objects with function in javascript

I am trying to write a function that will take two objects, people in this case, and swap only two of their attributes. Here is my function for the Person:
function Person (tall, weight, gender, iq, favoriteColor) {
this.tall = tall;
this.weight = weight;
this.gender = gender;
this.iq = iq;
this.favoriteColor = favoriteColor;
}
var joe = new Person("6-2", 180, "male", 130, "blue");
var bob = new Person("5-11", 150, "male", 120, "red");
So i want to swap JUST their IQs and favoriteColor.
So far I have:
function Swap(a, b) {
var i = a;
a = b;
b = i;
console.log(a, b);
}
This obviously swaps all their properties, but i cannot figure out how to swap just two and still have them log as objects. I have tried:
function Swap(a, b) {
var a = a.iq + a.favoriteColor;
var b = b.iq + b.favoriteColor;
var i = a;
a = b;
b = i;
console.log(a, b);
}
but this returns in the console:
120red 130blue.
Technically it swapped the two values, but their structure as an object is gone and the other three properties that they were supposed to keep of their own are also gone. How do I write the swap function to do this?
Thanks!
This is what you want. You need to swap the individual fields. You can't add them like you are doing. Also, it's best not to use the same name for variables that you've already declared, it's just too confusing.
function Swap(a, b) {
var i = a.iq;
a.iq = b.iq;
b.iq = i;
i = a.favoriteColor;
a.favoriteColor= b.favoriteColor;
b.favoriteColor = i;
console.log(a, b);
}
function Swap(a, b) {
var newBIq = a.iq
var newBColor = a.favoriteColor;
var newAIq = b.iq
var newAColor = b.favoriteColor;
a.iq = newAIq;
a.favoriteColor = newAColor;
b.iq = newBIq;
b.favoriteColor = newBColor
console.log(a, b);
}
Here you see the 4 values needed. I hope the naming helps understanding better than just i,j :D
If we take this solution to swap values...
b = [a, a = b][0];
...we could do this...
function Swap(a, b) {
b.iq = [a.iq, a.iq = b.iq][0];
b.favoriteColor = [a.favoriteColor, a.favoriteColor = b.favoriteColor][0];
}
and if you can use ECMAScript 6, you could even do
function Swap(a, b) {
[a.iq, b.iq] = [b.iq, a.iq]
[a.favoriteColor, b.favoriteColor] = [b.favoriteColor, a.favoriteColor]
}
This will swap all the values for the keys in an array of keys between objects a and b:
function Swap(a,b, keys){
for(var i=0; i<keys.length; i++){
var currentKey = keys[i];
var temp = a[currentKey];
a[currentKey] = b[currentKey];
b[currentKey] = temp;
}
}

Javascript nested objects from string

I've got an empty object and a string:
var obj = {};
var str = "a.b.c";
Is there a way I can turn this into
obj = { a: { b: { c: { } } } }
I can't quite wrap my head around this one and I'm not even sure if it would be possible.
var obj = {};
var str = "a.b.c";
var arr = str.split('.');
var tmp = obj;
for (var i=0,n=arr.length; i<n; i++){
tmp[arr[i]]={};
tmp = tmp[arr[i]];
}
ES6:
let str = "a.b.c",
arr = str.split('.'),
obj, o = obj = {};
arr.forEach(key=>{o=o[key]={}});
console.log(obj);
ES6/Reduced (array storage unnecessary):
let str = "a.b.c", obj, o = obj = {};
str.split('.').forEach(key=>o=o[key]={});
console.log(obj);
ES6/Array.prototype.reduce:
let str = "a.b.c", last;
let obj = str.split('.').reduce((o, val) => {
if (typeof last == 'object')
last = last[val] = {};
else
last = o[val] = {};
return o;
}, {});
console.log(obj);
This is from the yui2 yahoo.js file.
YAHOO.namespace = function() {
var a=arguments, o=null, i, j, d;
for (i=0; i<a.length; i=i+1) {
d=(""+a[i]).split(".");
o=YAHOO;
// YAHOO is implied, so it is ignored if it is included
for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) {
o[d[j]]=o[d[j]] || {};
o=o[d[j]];
}
}
return o;
};
See the source for documentation.
https://github.com/yui/yui2/blob/master/src/yahoo/js/YAHOO.js
This recursive function returns you the string representation of the desired object
//Usage: getObjectAsString('a.b.c'.split(/\./))
function getObjectAsString (array){
return !array.length ? '{}'
: '{"' + array[0] + '":' + getObjectAsString (array.slice(1)) + '}';
}
Now you can convert the output of getObjectAsString into object using
JSON.parse(getObjectAsString('a.b.c'.split(/\./)))
EDIT: Removed 'Input as String' version as it works only for single letter subparts in the namespace such as the one given in the question (a.b.c) which is generally not the case.
Here you go:
var string = "a.b.c",
array = string.split('.');
JSON.parse("{\"" + array.join('": {\"') + "\": {" +array.map(function () {return '}'}).join('') + "}")
Example
Here's my take on it:
function ensureKeys(str, obj) {
for(var parts = str.split('.'), i=0, l=parts.length, cache=obj; i<l; i++) {
if(!cache[parts[i]]) {
cache[parts[i]] = {};
}
cache = cache[parts[i]];
}
return obj;
}
var obj = {};
ensureKeys('a.b.c', obj);
// obj = { a: { b: { c: {} } } }

how can I declare a value deep in an object tree using variable properties in javascript

I am trying to have a javascript object tree behave like a php associative array in the following way.
var key1 = 'a';
var key2 = 'b';
var key3 = 'c';
var obj[key1][key2][key3] = 'd';
However, in javascript I believe you need to define each property/object pair individually, forming deeper leaves. Something like:
var obj[key1] = {};
var obj[key1][key2] = {};
...
Is there a way to simplify or shorten this script?
Thanks
I don't know if there's a "natural" way to do it, but you could do it like this:
function phpLike(){};
phpLike.prototype.set = function ()
{
var l = arguments.length;
if (l<2) return;
var o = this;
for (var i=0; i<l-2; i++)
{
if (o[arguments[i]] === undefined) o[arguments[i]] = {};
o = o[arguments[i]];
}
o[arguments[l-2]] = arguments[l-1];
}
// Test
var key1 = 'a';
var key2 = 'b';
var key3 = 'c';
var obj = new phpLike();
obj.set(key1, key2, key3, 'd');
alert(obj[key1][key2][key3]);
function setPropertyByKeyPath(obj, path, val) {
var key;
while (path.length > 1) {
key = path.shift();
obj[key] = typeof obj[key] === "object" ? obj[key] : {};
obj = obj[key];
}
obj[path.shift()] = val;
}
var o = {};
setPropertyByKeyPath(o, ['foo', 'bar'], 5);
alert(o.foo.bar)
Not directly, as far as I know, but how about using a little helper function?
function kv1(k, v) {
var o = { };
o[k] = v;
return o;
}
var obj = kv1(key1, kv1(key2, kv1(key3, 'd')));
I just thought of an answer inspired by Will's post: Construct a json string and then eval().
var obj = eval("{" + key1 + ": {... }};");
This kind of fulfils my search for a more concise way of declaring an object tree and deep leaf. But, it is ugly, confusing and I would avoid it like the plague.
var obj = { key1: { key2: { key3: 'd' } } }
This syntax is the basis of the format known as JSON: http://en.wikipedia.org/wiki/JSON

Categories

Resources