Combining 2 objects through a loop - javascript

let response = {
data1: {
names: ["John", "jim"]
},
data2: {
ages: [34, 24]
}
}
I want:
data: {
names: ["John", "jim"],
ages: [34,24]
}
Is there a way to merge these into 1 object without referencing response.data1 and response.data2? I know I can do const newObj = {...response.data1, ...response.data2} or Object.assign({}, response.data1, response.data1)... Can I do via a for in loop?

You could merge the values of the object using Object.assign() like this:
Object.assign({}, ...Object.values(response))
Explanation:
This is the syntax for Object.assign: Object.assign(target, source1, source2, ... etc). It basically takes all the properties from the source objects and updates the target object
The Object.values() bit returns the value of the response object. In this case, it's an array of objects like this:
[
{ names: ["John", "jim"] },
{ ages: [34, 24] }
]
You can spread the array and pass individual object as a parameter to Object.assign()
Here's a snippet:
let response = {
data1: {
names: ["John", "jim"]
},
data2: {
ages: [34, 24]
}
}
const output = Object.assign({}, ...Object.values(response))
console.log(output)
If it's too confusing you could use reduce:
Object.values(response)
.reduce((a, v) => ({ ...a, ...v }), {})
Or a simple loop:
const output = {}
for(const key in response)
Object.assign(output, response[key])

If you want to merge data1 and data2 using a for in loop, try this:
let response = {
data1: {
names: ["John", "jim"]
},
data2: {
ages: [34, 24]
}
}
var result = {}
for (data in response) {
if (response.hasOwnProperty(data)) {
[key] = Object.keys(response[data])
result[key] = response[data][key]
}
}
console.log(result)
The way it works is by getting the keys of data and data2, then using those keys, it gets the values and adds it to result

Related

javascript/lodash: cleaner way to spread properties?

I have a piece of data below. It's an object that contains 2 nested objects with arrays nested in those:
let data = {
obj1: {
names: ['joe'],
ages: false,
},
obj2: {
names: ['james'],
ages: true,
},
}
I want to return:
{
names: ['james','joe'],
ages: true,
}
Right now, I am doing this with:
const foo = Object.entries(data)[0][1] ?? [];
const foo2 = Object.entries(data)?.[1]?.[1] ?? [];
const finalData = {...foo, ...foo2 }
how can I clean that up using loDash's groupBy?
Use _.values() to get the two sub-objects, and then merge them using _.mergeWith(). If the values are an array, concat them, if not let _.mergeWith() handle the merge by returning undefined:
const data = {
obj1: {
names: ['joe', 'james'],
ages: false,
},
obj2: {
names: ['james'],
ages: true,
},
}
const result = _.mergeWith(
{}, ..._.values(data),
(a, b) => _.isArray(a) ? _.uniq([...a, ...b]) : undefined
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>

How to convert array of objects to object made up of only values

I have [ { key1:value1, key2:value2 }, { key3:value3, key4:value4 }, .... ]. I want to convert it to
{ value1: value2, value3: value4 }
Use Array#reduce to accumulate your object-data. Foreach object take from the values the first and add a new property with this name to the accumulated object with the value from the second object-value.
let array = [ { key1:'value1', key2:'value2' }, { key3:'value3', key4:'value4' }];
let res = array.reduce((acc, cur) => {
values = Object.values(cur);
acc[values[0]] = values[1];
return acc;
}, {});
console.log(res);
Assuming the inner objects always have 2 keys:
const arr = [ { key1:'value1', key2:'value2' }, { key3:'value3', key4:'value4' }]
const obj = {};
for (const innerObj of arr) {
const values = Object.values(innerObj);
obj[values[0]] = values[1];
}
console.log(obj) // { value1: 'value2', value3: 'value4' }
Note: you're question assumes an order for the keys in the inner objects, but that may not be guaranteed

Inside an Object.value loop how can I get the key

I have to create match condition based on an array my array will look like below
var groupData={
A:[
{rollnum: 1, name:'Arya', age:15},
{rollnum: 2, name:'Aryan', age:15}
],
B:[
{rollnum:11, name:'Biba', age:15},
{rollnum:12, name:'Bimisha', age:15}
]
}
I am looping using for loop. How can reduce the loops. Can any one suggest me a proper way for this
Object.values(groupData).flat().forEach((rowitem)=>{
query={};
Object.keys(rowitem).forEach(eachField=>{
query[eachField]["$in"].push(rowitem[eachField])
});
fullarray[Object.keys(groupData)]=matchQuery;
})
I need an output (fullarray) like below
{
'A':{
rollnum:{'$in':[1,2]},
name: {'$in':['Arya', 'Aryan']},
age: {'$in':[15]}
},
'B':{
rollnum:{'$in':[11,12]},
name: {'$in':['Biba', 'Bimisha']},
age: {'$in':[15]}
}
}
Here 'A' 'B' is not coming correctly
Don't use Object.values() since that discards the A and B keys.
Use nested loops, one loop for the properties in the object, and a nested loop for the arrays.
You need to create the nested objects and arrays before you can add to them.
var groupData = { A:
[ { rollnum: 1,
name: 'Arya',
age:15},
{ rollnum: 2,
name: 'Aryan',
age:15}, ],
B:
[ { rollnum: 11,
name: 'Biba',
age:15},
{ rollnum: 12,
name: 'Bimisha',
age:15} ] }
result = {};
Object.entries(groupData).forEach(([key, arr]) => {
if (!result[key]) {
result[key] = {};
}
cur = result[key];
arr.forEach(obj => {
Object.entries(obj).forEach(([key2, val]) => {
if (!cur[key2]) {
cur[key2] = {
"$in": []
};
}
cur[key2]["$in"].push(val);
});
});
});
console.log(result);

Javascript - denormalize JSON array using map function instead of nested for loop

I'm trying to get my head around map functions.
Here is my working code and output using a nested for loop:
var jsonsToAddTo = [
{'cat':'k1','key2':'a'},
{'cat':'k1','key2':'b'},
{'cat':'k2','key2':'a'},
{'cat':'k2','key2':'b'},
{'cat':'k3','key2':'a'}
]
var additionalData = [
{'pk':'k1','key3':'data1'},
{'pk':'k2','key3':'data2'},
{'pk':'k3','key3':'data3'},
]
// Adds a key value pair from sourceJson to targetJson based on a matching value
function denormalizeJsonOnKey(targetJsonArray,targetKeyToMatch, sourceJsonArray, sourceKeyToMatch, keyToAdd){
for(thisJson in targetJsonArray){
for(thatJson in sourceJsonArray){
if(targetJsonArray[thisJson][targetKeyToMatch]==sourceJsonArray[thatJson][sourceKeyToMatch]){
console.log('match');
targetJsonArray[thisJson][keyToAdd]=sourceJsonArray[thatJson][keyToAdd];
}
}
}
return targetJsonArray
}
console.log(denormalizeJsonOnKey(jsonsToAddTo,'cat',additionalData,'pk','key3'))
OUTPUT:
[
{ cat: 'k1', key2: 'a', key3: 'data1' },
{ cat: 'k1', key2: 'b', key3: 'data1' },
{ cat: 'k2', key2: 'a', key3: 'data2' },
{ cat: 'k2', key2: 'b', key3: 'data2' },
{ cat: 'k3', key2: 'a', key3: 'data3' }
]
I can't figure out how to handle the nesting using a map function on an array.
Using ES6 can simplify using Array#find() and Object#assign()
var data = [
{'cat':'k1','key2':'a'},
{'cat':'k1','key2':'b'},
{'cat':'k2','key2':'a'},
{'cat':'k2','key2':'b'},
{'cat':'k3','key2':'a'}
]
var data2 = [
{'pk':'k1','key3':'data1'},
{'pk':'k2','key3':'data2'},
{'pk':'k3','key3':'data3'},
]
const mergeData= (arr1, arr2, matchKey, filterKey, includeKey)=>{
arr1.forEach(o => {
const newObj ={};
const match = arr2.find(e => e[filterKey] === o[matchKey])
newObj[includeKey] = match ? match[includeKey] : null;
Object.assign(o, newObj);
});
}
mergeData(data, data2,'cat', 'pk', 'key3')
console.log(data)
Here is a solution that takes advantage of map and object spread to produce a new array with the desired key added into the target array's elements:
var jsonsToAddTo = [
{'cat':'k1','key2':'a'},
{'cat':'k1','key2':'b'},
{'cat':'k2','key2':'a'},
{'cat':'k2','key2':'b'},
{'cat':'k3','key2':'a'}
]
var additionalData = [
{'pk':'k1','key3':'data1'},
{'pk':'k2','key3':'data2'},
{'pk':'k3','key3':'data3'},
]
function denormalizeJsonOnKey(targetJsonArray,targetKeyToMatch, sourceJsonArray, sourceKeyToMatch, keyToAdd){
return targetJsonArray.map(thisJson => {
const addObj = sourceJsonArray.find(thatJson => thatJson[sourceKeyToMatch] === thisJson[targetKeyToMatch]);
return {
...thisJson,
...addObj ? {[keyToAdd]: addObj[keyToAdd]} : {},
}
});
}
console.log(denormalizeJsonOnKey(jsonsToAddTo, 'cat', additionalData, 'pk', 'key3'))
Note that this solution won't mutate the original array, so the jsonsToAddTo variable will be the same after you invoke the function. If you want to replace the original, you can always just re-assign it:
jsonsToAddTo = denormalizeJsonOnKey(jsonsToAddTo, 'cat', additionalData, 'pk', 'key3')
Try this,
using maps for both iteration,
var jsonsToAddTo = [{'cat':'k1','key2':'a'},{'cat':'k1','key2':'b'},
{'cat':'k2','key2':'a'},{'cat':'k2','key2':'b'},
{'cat':'k3','key2':'a'}]
var additionalData = [{'pk':'k1','key3':'data1'},{'pk':'k2','key3':'data2'},{'pk':'k3','key3':'data3'},
]
function denormalizeJsonOnKey(targetJsonArray,targetKeyToMatch, sourceJsonArray, sourceKeyToMatch, keyToAdd){
jsonsToAddTo.map((obj,index)=> {
additionalData.map((o,idx)=> {
if(obj[targetKeyToMatch]==o[sourceKeyToMatch]){
obj[keyToAdd]=o[keyToAdd];
}
})
})
return jsonsToAddTo
}
console.log(denormalizeJsonOnKey(jsonsToAddTo,'cat',additionalData,'pk','key3'))
var targetJsonArray = jsonsToAddTo.map(function(json, index) {
additionalData.forEach(function(data) {
if (data.pk === json.cat) {
json.key3 = data.key3;
}
})
return json;
})
Rather than nesting loops here, which will iterate the entire additionalData array for every entry in jsonsToAddTo, I suggest building an object map of the additionalData dataset once at the beginning, and then reference this within a .map on the target dataset:
var jsonsToAddTo = [
{'cat':'k1','key2':'a'},
{'cat':'k1','key2':'b'},
{'cat':'k2','key2':'a'},
{'cat':'k2','key2':'b'},
{'cat':'k3','key2':'a'}
]
var additionalData = [
{'pk':'k1','key3':'data1'},
{'pk':'k2','key3':'data2'},
{'pk':'k3','key3':'data3'},
]
// Adds a key value pair from sourceJson to targetJson based on a matching value
function denormalizeJsonOnKey(targetJsonArray,targetKeyToMatch, sourceJsonArray, sourceKeyToMatch, keyToAdd){
// Build an object of items keyed on sourceKeyToMatch
const sourceJsonMap = sourceJsonArray.reduce((obj, item) => (obj[item[sourceKeyToMatch]]=item, obj), {});
return targetJsonArray.map(item => {
const targetValue = item[targetKeyToMatch];
if (sourceJsonMap.hasOwnProperty(targetValue)) {
item[keyToAdd] = sourceJsonMap[targetValue][keyToAdd];
}
return item;
});
}
console.log(denormalizeJsonOnKey(jsonsToAddTo,'cat',additionalData,'pk','key3'))
Doing it this way should be far more efficient, especially if the dataset you are working on is fairly large.

changing an array of javascript objects with a single key to an array that contains the objects' data

I currently have data in the following format:
var anArray = [
obj1: {
key1: data1
},
obj2: {
key2: data2
},
];
I would like the data to instead be in the following format:
var array2 = [data1, data2];
for some reason, I cannot figure out a concise way to to this. I know it could be done with a forEach loop that iterates over each object and pushes it onto a new array, but I would prefer to be more elegant (and shorter if possible) than that.
const anArray = {
obj1: {
key1: "A"
},
obj2: {
key2: "B"
},
};
const result = Object.keys(anArray).map(key => {
const obj = anArray[key];
return Object.keys(obj).map(key => obj[key])[0];
});
console.log(result);
Given that anArray is actually properly structured to be valid, then you could do the following:
Note that in this case anArray isn't an actual array but rather a object literal
var anArray = {
obj1: {
key1: "data1"
},
obj2: {
key2: "data2"
},
};
var array2 = []
for(i in anArray){
for(j in anArray[i]){
array2.push(anArray[i][j])
}
}
console.log(array2)
https://jsfiddle.net/wh4r0w5s/
Try with:
const arr1 = [
{key1:'value1'},
{key2:'value2'}
]
const res = arr1.map(obj => {
return Object.keys(obj).map(val => obj[val])
}).reduce((acc,v) => {
return acc.concat(v);
},[]);
console.log(res);
update
But if you have the following form:
var anArray = [
obj1: {
key1: data1
},
obj2: {
key2: data2
},
];
It's better to apply a recursive function, as follow:
const arr1 = [
{
obj1:{key1:'value1',key3:'value3'}
},
{
obj2:{key2:'value2'}
}
]
const getValuesFromObj = (obj) => {
if(typeof obj === 'string')
return obj;
return Object.keys(obj).map(key => {
return getValuesFromObj(obj[key]);
}).reduce((acc,v) => {
return acc.concat(v);
},[]);
}
const r2 = getValuesFromObj(arr1);
console.log(r2);

Categories

Resources