Two object arrays: merge with same key - javascript

I have two object arrays. I want to merge with key with value
var a = [{"fit":["34","32","30","28"],"size":["x"]}]
var b = [{"size":["s","m","xl"],"fit":["36"]}]
Expected Output should be
Obj=[{"fit":["34","32","30","28","36"],"size":["x,"s","m","xl"]}]
My Code is
let arr3 = [];
b.forEach((itm, i) => {
arr3.push(Object.assign({}, itm, a[i]));
});
alert(JSON.stringify(arr3))
it gives [{"size":["x"],"fit":["34","32","30","28"]}] which wrong.

Use Array.reduce().
// Combine into single array (spread operator makes this nice)
const myArray = [...a, ...b];
// "reduce" values in array down to a single object
const reducedArray = myArray.reduce((acc, val) => {
return [{fit: [...acc.fit, ...val.fit], size: [...acc.size, ...val.size]}];
});
Edit: if you want the reducer to merge objects regardless of what keys and fields it has then you can do by iterating over the keys of the objects and merging them dynamically:
const reducedArray = myArray.reduce((acc, val) => {
const returnObject = {};
for (const eaKey in acc) {
returnObject[eaKey] = [...acc[eaKey], ...val[eaKey]];
}
return [returnObject];
});
If the fields of the objects aren't guaranteed keys then you will need to get even more dynamic in detecting the type of merge and how to do it, but it's possible and I will leave that as an exercise for you to figure out. :)
Note that if there are duplicate values in each of the "fit" and "size" arrays, they will not be deduplicated. You'd have to do that manually as a separate step either with extra logic in the reduce function or afterwards.

combine a and b in a single array then reduce it starting with an array having an object with empty fit and size arrays:
var a = [{ fit: ["34", "32", "30", "28"], size: ["x"] }];
var b = [{ size: ["s", "m", "xl"], fit: ["36"] }];
var obj = [...a, ...b].reduce(
(acc, curr) => {
Object.keys(curr).forEach(k => {
acc[0][k] = [...new Set([...(acc[0][k] || []), ...curr[k]])];
});
return acc;
},
[{}]
);
console.log(obj);

You can create a combine function that takes fit and size from any two objects and merges them.
Use it as a reducer to combine everything.
let combine = ({fit, size}, {fit: fit2, size: size2}) =>
({ fit: [...fit, ...fit2], size: [...size, ...size2] });
let result = [...a, ...b].reduce(combine);
Example:
var a = [{"fit":["34","32","30","28"],"size":["x"]}, {"fit": ["10", "11"], "size":["xxxxxxxxl"]}]
var b = [{"size":["s","m","xl"],"fit":["36"]}];
let combine = ({fit, size}, {fit: fit2, size: size2}) =>
({ fit: [...fit, ...fit2], size: [...size, ...size2] });
let result = [...a, ...b].reduce(combine);
console.log(result);

If you don't want to use the keys directly you could try
const arr3 = b.reduce((carry, current, index) => {
Object.keys(current)
.forEach(key => {
Object.assign(carry, { [key]: Array.prototype.concat.call(current[key], a[index][key])});
});
return carry;
}, {});

Related

How to generate this JSON object?

I have an array with the following values:
['persona1', 'Persona2', 'Persona3', 'Persona4']
And I have another array with the names of each person:
['JUAN', 'CARLOS', 'PEDRO','MATEO']
I need to generate a JSON object like the following:
{ persona1: 'JUAN', persona2: 'CARLOS', persona3: 'PEDRO', persona4: 'MATEO' }
Each value in the first array becomes the key for the corresponding value in the second array.
How can I do this in Javascript?
Loop over the array and generate the object dynamically.
let arr1 = [ 'foo', 'bar' ]
let arr2 = [ 'baz', 'qux' ]
let obj = {}
for (let i = 0; i < arr1.length; i++) obj[arr1[i]] = arr2[i];
console.log(obj);
You could use reduce here
const arr1 = ["persona1", "Persona2", "Persona3", "Persona4"];
const arr2 = ["JUAN", "CARLOS", "PEDRO", "MATEO"];
const result = arr1.reduce((acc, curr, i) => {
acc[curr] = arr2[i];
return acc;
}, {});
console.log(result);
You can create an empty object, loop over the first array, and take each item in the array as the key, and take each item of the second array as the value.
Then you can you the JSON.stringify() function to convert that object to JSON string.
const arr1 = ['persona1', 'Persona2', 'Persona3', 'Persona4']
const arr2 = ['JUAN', 'CARLOS', 'PEDRO', 'MATEO']
const output = {}
arr1.forEach((item, i) => output[item] = arr2[i])
console.log(JSON.stringify(output))
const personKeyArr = ['persona1', 'Persona2', 'Persona3', 'Persona4']
const personValArr = ['JUAN', 'CARLOS', 'PEDRO','MATEO']
const retValue = {}
personKeyArr.forEach((x,i)=>retValue[x] = [personValArr[i]])
What you want to do is a combination of zipping two arrays together and then converting the resulting pairs into the key/value entries in an object. As #Phil mentioned in their comment, the lodash library has a function to do this called zipObject, but if you don't want to load that entire library, it's not hard to create your own with reduce. Here's one version (found at https://lowrey.me/lodash-zipobject-in-es6-javascript/):
const zipObject = (props, values) => {
return props.reduce((prev, prop, i) => {
return Object.assign(prev, { [prop]: values[i] });
}, {});
};
Running it on your data:
keys = ['persona1', 'Persona2', 'Persona3', 'Persona4']
nombres = ['JUAN', 'CARLOS', 'PEDRO','MATEO']
zipObject(keys, nombres)
//=>
{
persona1: 'JUAN',
Persona2: 'CARLOS',
Persona3: 'PEDRO',
Persona4: 'MATEO'
}

How can I do total count of values accordingly selected feild in array

I have a array of objects, for exemple:
let arr = [
{title:apple,quantity:2},
{title:banana,quantity:3},
{title:apple,quantity:5},
{title:banana,quantity:7}
];
array containe many same objects, and i want recived array with uniqe object :
let result = [
{title:apple,quantity:7},
{title:banana,quantity:10}
]
How can I do this?
You can iterate over your array and filter out all the object with same title. Then use reduce to add all the quantity and return a new object. Code is below,
let newArr = [];
arr.forEach((currentObj) => {
const alreadyExists = newArr.findIndex(item => currentObj.title === item.title) > -1;
if(!alreadyExists) {
const filtered = arr.filter(item => item.title === currentObj.title);
const newObject = filtered.reduce((acc, curr) => { return {...acc, quantity: acc.quantity += curr.quantity}}, {...currentObj, quantity: 0})
newArr.push(newObject);
}
})
console.log(newArr);
This is done on a phone so may have some typos but the gist is there:
const resultObj = arr.reduce((acc,curr) =>{
acc[curr.title] = acc[curr.title]== undefined? curr.quantity: acc[curr.title] + curr.quantity
return acc
},{})
const resultArr = Object.entries(resultObj).map([key,value]=>({title:key,quantity:value}))
You could do that in "one line" using arrow function expressions but it won't be very readable unless you know what's happening inside:
let arr = [
{title: "apple",quantity:2},
{title: "banana",quantity:3},
{title: "apple",quantity:5},
{title: "banana",quantity:7}
];
let newArr = [...arr.reduce((acc, {title, quantity}) =>
(acc.set(title, quantity + acc.get(title) || 0), acc), new Map())
].map(([title, quantity]) => ({title, quantity}));
console.log(newArr);
So basically the first part is the reduce method:
arr.reduce((acc, {title, quantity}) =>
(acc.set(title, quantity + acc.get(title) || 0), acc), new Map())
That will returns a Map object, where each title is a key (e.g. "apple") and the quantity is the value of the key.
At this point you have to convert the Map object into an array again, and you do it using the spread syntax.
After you got an array back, you will have it in the following form:
[["apple", 7], ["banana", 10]]
But that is not what you want yet, not in this form, so you have to convert it using the array's map method:
<array>.map(([title, quantity]) => ({title, quantity}))
To keep it concise it uses the destructuring assignment

Array of dictionaries to a single array of dictionary in javascript

I have a javascript array as
arr = [{"class":"a"},{"sub_class":"b"},{"category":"c"},{"sub_category":"d"}]
I want a new array as:
new_arr = [{"class":"a", "sub_class":"b", "category":"c", "sub_category":"d"}]
Is it possible to do this in Javascript without using a for loop to iterate through arr?
You can use Object.assign:
const array = [{
"class": "a"
}, {
"sub_class": "b"
}, {
"category": "c"
}, {
"sub_category": "d"
}]
const mergedObject = Object.assign({}, ...array);
// And put in an Array if that was intentional
const newArray = [mergedObject];
console.log(newArray);
I think that you want to merge objects. You could either use a spread operator or Object.assign. I don't see the point of having a single object inside an array. Considering your requirements you could do:
const merged = arr.reduce((list, curr) => {
return Object.assign({}, list, curr);
}, {});
const newArr = [merged];
You can try this.
var arr = [{"class":"a"},{"sub_class":"b"},{"category":"c"},{"sub_category":"d"}];
var res=[];
var res1=[];
res=Object.assign(...arr);
res1.push(res);
console.log("Result: ",res1);

How to rename JSON element in Nodejs

I have an API that response JSON data like this-
{
"unitcode":"apple",
"description":"bus",
"color":"red",
"intent":"Name 1"
}
I want to change like this-
{
"Value1":"apple",
"Value2":"bus",
"value3":"red",
"value4":"sale"
}
Presently, I can code to rename single key but i want some code to replace all key in one shot. my code like this-
request(baseurl)
.then( body => {
var unit = JSON.parse(body);
unit.intent = "sales"
unit.value1 = unit.unitcode
delete unit.unitcode;
console.log(unit)
console.log(unit.Value1)
var unit2 = JSON.stringify(unit)
// let code = unit.description;
conv.ask('Sales is 1 million metric tonnes ' + unit2);
})
please help me out on this and please little elaborate also to learn something new. thanks
Create a Map of original key to new key (transformMap). Convert the object to pairs of [key, value] with Object.entries(), iterate with Array.map() and replace the replacement key from the Map (or the original if not found). Convert back to an object with Object.toEntries():
const transformMap = new Map([
['unitcode', 'Value1'],
['description', 'Value2'],
['color', 'Value3'],
['intent', 'Value4']
]);
const transformKeys = obj =>
Object.fromEntries(
Object.entries(obj)
.map(([k, v]) => [transformMap.get(k) || k, v])
);
const obj = {
"unitcode": "apple",
"description": "bus",
"color": "red",
"intent": "Name 1"
};
const result = transformKeys(obj)
console.log(result)
If you know the object structure and it is constant, you could just use destructing like so.
const data = {
"unitcode":"apple",
"description":"bus",
"color":"red",
"intent":"Name 1"
};
// If the object is fixed and the fields are known.
const mapData = ({ unitcode, description, color, intent }) => ({
Value1: unitcode,
Value2: description,
Value3: color,
Value4: intent
});
console.log(JSON.stringify(mapData(data)));
But if the object has an unknown number of properties:
const data = {
"unitcode":"apple",
"description":"bus",
"color":"red",
"intent":"Name 1"
};
// If the object is fixed and the fields are known.
const mapData = (data) => {
return Object.keys(data).reduce((a,v,i) => {
a[`Value${i+1}`] = data[v];
return a;
}, {});
};
console.log(JSON.stringify(mapData(data)));
You can edit the array to have the values you need
let i=0,j=0,unit1={};
let unit = JSON.parse(body);
let unit3=["val1","val2","val3","val4"]
let unit5=Object.values(unit);
for(let key in unit){
unit1[unit3[i++]]=unit5[j++];
}
var unit2 = JSON.stringify(unit1)
console.log('Sales is 1 million metric tonnes \n' + unit2);
//Sales is 1 million metric tonnes
//{"val1":"apple","val2":"bus","val3":"red","val4":"Name 1"}
Well your target is to modify the keys and retain the value
In that context, you can iterate through your data. To dynamically generate keys as Value1, Value2, etc, we will append Value with iteration index which is going to be unique always.
const modifyInput = (input) => {
const modifiedInput = {}
Object.values(input).forEach((item, index) => {
modifiedInput[`Value${index + 1}`] = item
})
return modifiedInput
}
Use this function, pass your input and get your desired result

Print the array objects inside another array into a specific format in javascript

Generate an array of objects in a format from an array of objects inside another array .
The Given array is :
let target =
[[{key: "subscriber_id", value: "1"},
{key: "msisdn_value", value: "2"}],
[{key: "subscriber_id", value: "3"},
{key: "msisdn_value", value: "4"}
]]
The expected array of objects should be :
result = [
{"subscriber_id":"1","msisdn_value":"2"},
{"subscriber_id":"3","msisdn_value":"4"},
]
Use nested map calls with Object.fromEntries and Object.values for a clean and concise solution like so:
const result = target.map(e => Object.fromEntries(e.map(Object.values)));
Or, for a more efficient solution, use reduce:
const result = target.map(e => e.reduce((a, { key, value }) => (a[key] = value, a), {}));
You can use map and destructuring
let target = [[{key: "subscriber_id",value: "1"},{key: "msisdn_value",value: "2"}],[{key: "subscriber_id",value: "3"},{key: "msisdn_value",value: "4"}]]
let final = target.map(data => {
let [{key:a,value:b},{key:c,value:d}] = data
return { [a]:b, [c]:d }
})
console.log(final)
Loop through each element if there are more than two elements in inner arrays
let target = [[{key: "subscriber_id",value: "1"},{key: "msisdn_value",value: "2"}],[{key: "subscriber_id",value: "3"},{key: "msisdn_value",value: "4"},{key: "key",value: "value"}]]
let final = target.map((data) => {
return data.reduce((obj,{key,value})=>{
obj[key] = value
return obj
},{})
})
console.log(final)

Categories

Resources