Group like JSON objects into arrays - javascript

I have a model returned by a library in the following format:
var givenData = [{"fName": "john"}, {"fName": "mike"}, {"country": "USA"}]
How do I group the "fName" together and add '[]' to get:
{ 'fName[]': ['john','mike'],'country[]': ['USA'] };
**Note country and fName are not related at all.

Suggestion (using ES6 syntax)
const transformData = (data) => {
const newData = {}
data.forEach( (item) => {
for (let key in item) {
const newKey = key + "[]"
if (!newData.hasOwnProperty(newKey)) newData[newKey] = []
newData[newKey].push(item[key])
}
})
return newData
}
/* added some extra keys just to test */
let givenData = [
{"fName": "john", "country": "England"},
{"fName": "mike"},
{"country": "USA"},
{"language": "English"}
]
console.log(transformData(givenData))
/*
{
"fName[]": ["john","mike"],
"country[]": ["England","USA"],
"language[]":["English"]
}
*/

You can iterate over the array and push the date to the desired field.
var givenData = [{"fName": "john"}, {"fName": "mike"}, {"country": "USA"}]
var result = {
'fName[]': [],
'country[]': []
};
givenData.forEach(function (data) {
if (data.fName) {
result['fName[]'].push(data.fName);
}
if (data.country) {
result['country[]'].push(data.country);
}
});
console.log(result);

You could take the key and build an object with the key and arrays as properties.
var givenData = [{"fName": "john"}, {"fName": "mike"}, {"country": "USA"}],
grouped = givenData.reduce(function (r, o) {
var key = Object.keys(o)[0] + '[]';
r[key] = r[key] || [];
r[key].push(o[Object.keys(o)[0]]);
return r;
}, Object.create(null));
console.log(grouped);

In ES6:
const newData = givenData.reduce(function (r, o) {
const key = `${Object.keys(o)[0]}[]`;
return { ...r, [key]: [ ...r[key], o[key] ] }
}, {});
This doesn't modify your original data and is very clean.

Related

How to convert object key value pair with array as values to multi objects of key value pair?

I have an object with key-value pair and its value as an array of elements.
{
status: ["new", "old"],
place: ["york", "blah"]
}
I'm trying to convert it into multiple array objects of key-value pair like below.
{
"newObj1": [
{ "status": "new" },
{ "status": "old" }],
"newObj2": [
{ "place": "york" },
{ "place": "blah" }]
}
Is there any way to achieve the above structure? I have tried couple of methods using array reduce methods but it doesn't give in the desired output.
let value= {
status: ["new", "old"],
place: ["york", "blah"]
}
Object.keys(value).map((key) => [key, value[key]]);
You can do something like this
const obj = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = {};
Object.keys(obj).forEach((key, index) => {
result[`newObj${index + 1}`] = obj[key].map(item => ({[key]: item}));
});
console.log(result);
Here's a solution that uses Array.reduce():
const value = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = Object.keys(value).reduce((acc, key, i) => {
acc["newObj" + (i + 1)] = value[key].map(k => ({ [key]: k }));
return acc;
}, {});
console.log(result);
Here is my way of accomplishing that.
let source = {
status: ["new", "old"],
place: ["york", "blah"]
};
let destination = {}; // make room for the destinoation object
Object.keys(source).forEach((key, index) => {
let obj = "newObj" + (index + 1); // assume all objects are named "newObj1,2,3,etc"
if (!destination[obj]) { // check if the object exists already
// if not, then crate an empty array first
destination[obj] = [];
}
// loop through all items in the source element array
source[key].forEach(value => {
// create an object from the array element
let subObj = {};
subObj[key] = value;
// push that object to the destination
destination[obj].push(subObj);
});
});
console.log(destination);
const data = {
status: ["new", "old"],
place: ["york", "blah"]
};
let result = Object.fromEntries( Object.entries(data).map( ([key, [first, second]], index) => {
return [ `newObj${index}`, [ { [key]: first }, { [key]: second } ] ];
} ) );
console.log(result);
Here's an idiomatic solution using .reduce inside .reduce:
Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
Here's a live example:
const data = {
status: ['new', 'old'],
place: ['york', 'blah']
};
const result = Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
console.log(result);
/*
{
newObj1: [
{ status: 'new' },
{ status: 'old' }
],
newObj2: [
{ place: 'york' },
{ place: 'blah' }
]
}
*/
For those who fail to understand map and reduce, here's a fairly naive solution but it will work:
newObjCounter = 1
orig = { status: [ 'new', 'old' ], place: [ 'york', 'blah' ] }
newObject = {}
//Initialise object with new keys with arrays as values
for(var key in orig){
newObject["newObj"+initialCounter] = []
initialCounter++
}
//Loop through keys of the original object and dynamically populate the new object
for(var key in orig){
index = "newObj"+objCounter
newObject[index].push({[key]:orig[key]})
objCounter++
}
console.log(newObject)

How to split and merge javascript object with respect to index of array attribute

How to split and merge javascript object with respect to index of array attribute.
I have fields like that.
var myFields = {
Country: "USA",
State: "DC",
Cataogry: ["Value1", "Value2"],
Level: ["Level1", "Level2"]
};
I want to derive two from here like this. Output : -
var fields = [
{ Country: "USA", State: "DC", Cataogry: "Value1", Level: "Level1" },
{ Country: "USA", State: "DC", Cataogry: "Value2", Level: "Level2" }
];
So When I am using my code I am getting 4 arrays instead of two. Can anybody help me with how to merge with respect to the index.
Here is what I have tried:
var myObj = {};
for (var i = 0; i < fields.length; i++) {
myObj[fields[i].key] = fields[i].Value;
}
var myObjList = [];
var listFlag = false;
Object.keys(myObj).forEach(function(key) {
if (Array.isArray(myObj[key])) {
listFlag = true;
myObj[key].forEach(function(el) {
var objCopy = JSON.parse(JSON.stringify(myObj));
objCopy[key] = el;
myObjList.push(objCopy);
});
}
});
if (!listFlag) {
myObjList.push(myObj);
}
You could use map method.
var myFields = {
"Country" : "USA",
"State" : "DC",
"Cataogry" : ["Value1","Value2"],
"Level" : ["Level1","Level2"]
}
var fields = myFields.Cataogry.map((item, index) => ({
Country : myFields.Country,
State : myFields.State,
Cataogry: myFields.Cataogry[index],
Level : myFields.Level[index]
} ));
console.log(fields);
You could take a dynamic approach and iterate all entries and have a look to value.
If value is an array, map the values along with the object at the same index or take the first object as pattern.
If value is no array, map the accumulator and add the actual key/value pair to all objects.
var object = { Country: "USA", State: "DC", Category: ["Value1", "Value2"], Level: ["Level1", "Level2"] },
result = Object
.entries(object)
.reduce(
(r, [key, value]) => Array.isArray(value)
? value.map((v, i) => ({ ...(r[i] || r[0]), [key]: v }))
: r.map(o => ({ ...o, [key]: value })),
[{}]
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can map it. Here is my try. I'm assuming category and level are of the same length.
var myFields = {
Country: "USA",
State: "DC",
Cataogry: ["Value1", "Value2"],
Level: ["Level1", "Level2"]
};
var result = myFields.Cataogry.map((Cataogry, i) => ({
...myFields,
Cataogry,
Level: myFields["Level"][i]
}));
console.log(result);

How to make json tree through group by json data?

Please take a look at my current json.
[
{"mode": "AR","fname": "ta","lname":"da","w_lng":"2.xx","w_lat":"1.xx"....},
{"mode": "AR","fname": "ta","lname":"da","w_lng":"3.xx","w_lat": "4.xx"....},
{"mode": "AR","fname": "ka","lname":"ja","w_lng":"6.xx","w_lat": "5.xx"....}
]
Now What I am looking for:
{
"mode": "AR",
"results": [
{
"fname": "ta",
"lname": "da",
"w_level": [
{ "w_lng": "2.xx",
"w_lat": "1.xx"
"anothelevel":[........]
},
{"w_lng": "3.xx",
"w_lat": "4.xx"
"anothelevel":[........]
}
]
}
{
"fname": "ka",
"lname": "ja",
"w_level": [
{
"w_lng": "x.xx",
"w_lat": "x.xx"
.....................
}
]
}
]
}
It is same as we do in SQL group by. suppose First group by world, then country, then city, then village etc. I was tried through group by. but the result is not my expected output. Please suggest me what should I do.
objMap = {};
for (let temp of obj) {
if (!objMap[temp.mode]) {
objMap[temp.mode] = { mode: temp.mode, results: [] }
}
let tempObj = { w_level: [], fname: temp.fname, lname: temp.lname };
let w_level = {};
for (let key of Object.keys(temp)) {
if (key !== "fname" && key !== 'lname' && key !== 'mode') {
w_level[key] = temp[key];
}
}
tempObj.w_level.push(w_level)
objMap[temp.mode].results.push(tempObj)
}
NOTE:get object by using Object.values(objMap);
Solution using reduce:
const inArr = [{"mode":"AR","fname":"Kiran","lname":"Dash","w_lng": "1.23", "w_lat": "2.23"},{"mode":"AR1","fname":"Suman","lname":"Dash","w_lng": "3.23", "w_lat": "4.23"},{"mode":"AR","fname":"Raman","lname":"Dash","w_lng": "5.23", "w_lat": "6.23"},{"mode":"AR","fname":"Milan","lname":"Dash","w_lng": "7.23", "w_lat": "8.23"},{"mode":"AR1","fname":"Naman","lname":"Dash","w_lng": "8.23", "w_lat": "9.23"},{"mode":"AR2","fname":"Phulan","lname":"Dash","w_lng": "10.23", "w_lat": "11.23"}]
console.log(
Object.values(inArr.reduce((item, currItem) => {
var { mode, fname, lname } = currItem;
if (!item[mode]) item[mode] = { mode, results: [] };
let w_level = {};
for (let key of Object.keys(currItem)) {
if (key !== "fname" && key !== 'lname' && key !== 'mode') {
w_level[key] = currItem[key];
}
}
item[mode].results.push({fname: fname, lname: lname, w_level: [w_level]});
return item;
}, {}))
);
Code walk through:
Loop over the input array, and group into an object indexed by mode.
Create an object with a result array if the mode doesn't exist yet, and push to that array.
Note: For the sake of simplicity, I have done it to one level. Please use the same approach to create multiple levels if you want.
------At last I found solution-----------
const reduceArrayByKeys = (inArr, keys, restKey) => {
const reduced = inArr.reduce((prev, cur) => {
const copied = { ...cur }
keys.forEach(key => delete copied[key])
const existing = prev.find(item => keys.every(key => item[key] === cur[key]))
if (existing) {
existing[restKey].push(copied)
} else {
const newItem = {}
keys.forEach(key => newItem[key] = cur[key])
newItem[restKey] = [copied]
prev.push(newItem)
}
return prev
}, [])
return reduced
}
const reduced = reduceArrayByKeys(inArr, ['mode'], 'results')
reduced.forEach(item => {
const results = item.results
item.results = reduceArrayByKeys(results, ['fname', 'lname'], 'w_level')
item.results.forEach(child => {
child.w_level = reduceArrayByKeys(child.w_level, ['w_lng', 'w_lat'],
'other')
})
})

How to add properties for all the keys and values in an object?

I have a Javascript Object :
{
"Central":73322346.47533998,
"East":87801368.39711998,
"North":76468694.37534,
"South":142687496.66816995,
"West":76815749.40554999
}
I want to map this object into an array that look like this
[
{"name" :"Central ,"size" : 73322346.47533998},
{"name" : "East", "size" : 87801368.39711998},
{"name": "North","size":76468694.37534},
{"name": "South","size" :142687496.66816995},
{"name":"West","size":76815749.40554999}
]
How do I go about?
do like this:
obj = {"Central":73322346.47533998,"East":87801368.39711998,"North":76468694.37534,"South":142687496.66816995,"West":76815749.40554999}
out = [];
Object.keys(obj).forEach(function(d){ out.push({name: d, size: obj[d]});})
//out will contain your formatted data
In ES2017 you can do:
Object.entries(obj).map(([name, size])=> ({name, size}))
var obj = {
"Central":73322346.47533998,
"East":87801368.39711998,
"North":76468694.37534,
"South":142687496.66816995,
"West":76815749.40554999
}
var res = Object.entries(obj).map(([name, size])=> ({name, size}));
console.log(res);
In ES2011 (5.1), ES2015 (6),.... and onward you can do:
Object.keys(obj).map(function(k) {
return {name: k, size: obj[k]}
})
var obj = {
"Central":73322346.47533998,
"East":87801368.39711998,
"North":76468694.37534,
"South":142687496.66816995,
"West":76815749.40554999
}
var res = Object.keys(obj).map(function(k) {
return {name: k, size: obj[k]}
})
console.log(res)
You can loop over the keys of the object to get the array of objects as expected:
var data = {"Central":73322346.47533998,"East":87801368.39711998,"North":76468694.37534,"South":142687496.66816995,"West":76815749.40554999};
var res = [];
Object.keys(data).forEach((key)=>{
res.push({
name: key,
size: data[key]
});
});
console.log(res);
A simple way to do this is to interate over the keys of the input object using a for..in loop:
const input = {
"Central": 73322346.47533998,
"East": 87801368.39711998,
"North": 76468694.37534,
"South": 142687496.66816995,
"West": 76815749.40554999
};
let output = [];
for (const key in input)
{
output.push({ "name": key, "size": input[key] });
}
console.log(output);
This is probably the fastest way to achieve the desired output.

convert JSON object to a different one

i have this json:
[
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
]
and i want to convert it to:
[
{ "name": "AF28110", "price": 33456.75},
{ "name": "AF27989", "price": 13297.26}
]
I have tried various making it with .map() but i cannot make it work.
does anyone have any idea how to do this?
thank you
You can try following code:
let output = [];
input.forEach(obj => Object.getOwnPropertyNames(obj).forEach(key => output.push({name: key, price: obj[key]})))
Object.getOwnPropertyNames will give you names of your properties and then you can transform each name to a separate output array item.
Using map:
const data = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
]
const out = Object.keys(data[0]).map(el => {
return { name: el, price: data[0][el] };
});
console.log(out)
Here's a way using concat, Object.keys, and map. You can take each item from the array, get the keys from that object, and then map each key to the name/price object you want. Do that for each item, then flatten the result (using concat).
Example:
const arr = [{
"AF28110": 33456.75,
"AF27989": 13297.26
}]
const result = [].concat(...arr.map(o => Object.keys(o).map(k => ({name: k, price: o[k]}))))
console.log(result);
If you have multiple objects on the array, you can use reduce
let arr = [
{"AF28110": 33456.75,"AF27989": 13297.26},
{"AF28111": 33456.20,"AF27984": 13297.88}
];
let result = arr.reduce((c, v) => c.concat(Object.entries(v).map(o => {return {name: o[0],price: o[1]}})), []);
console.log(result);
Try this,
var text = '[{"AF28110": 33456.75,"AF27989": 13297.26}]';
var obj = JSON.parse(text);
var result = [];
for (i = 0; i < obj.length; i++) {
var keys = Object.keys(obj[i]);
for (j = 0; j < keys.length; j++){
result[j] = '{ "name":' +keys[j] + ', "price":' + obj[i][keys[j]]+'}';
}
}
console.log(result);
Thanks.
Ways to achieve :
Using Object.keys method :
var jsonObj = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
];
var res = Object.keys(jsonObj[0]).map(item => {
return {"name": item, "price": jsonObj[0][item] };
});
console.log(res);
Using Object.getOwnPropertyNames method :
var jsonObj = [
{
"AF28110": 33456.75,
"AF27989": 13297.26
}
];
var res = Object.getOwnPropertyNames(jsonObj[0]).map(item => {
return {"name": item, "price": jsonObj[0][item] };
});
console.log(res);

Categories

Resources