node.js + Object Array - javascript

In my node app i have to construct an object array from another object array.
Consider my object array as..
[ { id_0: 356, id_1: 33, name_1: 'aaaa' },
{ id_0: 756, id_1: 89, name_1: 'bbbbb' },
{ id_0: 456, id_1: 89, name_1: 'ccccc' },
{ id_0: 356, id_1: 27, name_1: 'dddd' } ]
I have to construct an object array as like below:
[{
"356":["33":"aaaa","27":"ddddd"],------------->Changes made
"456":[{"89":"cccc"}],
"756":[{"89":"bbbbbbbb"}]
}]
I tried using async.map.But i cant get the right way to do it.Please help me to solve this.Thanks in advance...

You can use Array.prototype.reduce function, like this
console.log(data.reduce(function(result, current) {
var obj = {};
result[current.id_0] = result[current.id_0] || [];
obj[current.id_1] = current.name_1;
result[current.id_0].push(obj);
return result
}, {}));
Output
{ '356': [ { '33': 'aaaa' }, { '27': 'dddd' } ],
'456': [ { '89': 'ccccc' } ],
'756': [ { '89': 'bbbbb' } ] }
If you want to convert this to an array of object, just wrap the result of data.reduce with [] like this
console.log([data.reduce(function(result, current) {
...
...
}, {})]);
Edit:
result[current.id_0] = result[current.id_0] || [];
this line makes sure that result[current.id_0] is an array. If the value of result[current.id_0] is truthy, then that value is rturned but if it is not, then [] will be returned. So, a new array will be created and assigned to result[current.id_0]. It is actually a shorthand for
if (result.hasOwnProperty(current.id_0) === false) {
result[current.id_0] = [];
}
Edit 2: If you like to keep the grouped elements as an object, you could do like this
console.log(data.reduce(function(result, current) {
result[current.id_0] = result[current.id_0] || {};
result[current.id_0][current.id_1] = current.name_1;
return result
}, {}));
Output
{ '356': { '27': 'dddd', '33': 'aaaa' },
'456': { '89': 'ccccc' },
'756': { '89': 'bbbbb' } }

Related

JavaScript modify Array of Objects and alter contained data

I am having difficulties formatting some data. Currently, I receive data in the following structure.
[
{
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
}
]
I essentially need to modify this or even create a new object, that takes the following structure.
[
{
id: 1, //q1
answers: [
{
answer: '5',
},
],
},
{
id: 2, //q2
answers: [
{
answer: '13',
},
{
answer: '12',
},
],
},
{
id: 3, //q3
answers: [
{
answer: 'test',
},
],
},
];
So the id in the above would be obtained by remove the q and getting the number in the first data object. It would then have an answers array that would have an object for each answer.
I have been attempting this but have gotten lost. I don't know if I should use loops, mapping, filters etc. To be honest, the furthest I have got so far is obtaining the keys
var modified = data.map(function(item) {
return Object.keys(item)
})
I have created a JSFiddle where I have been attempting to do this.
Is there any way I can achieve the data I am after?
Many thanks
Please use map function.
const data = {
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
};
const result = Object.keys(data).map(key => {
let item = {id: key.substring(1), answers: []};
if(typeof data[key] === "string")
item.answers.push({answer: data[key]});
else
item.answers = data[key].map(val => ({answer: val}));
return item;
});
console.log(result)
const inputData = [
{
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
}
]
function answerMapper(objVal, id){
return Array.isArray(objVal)
?
{ id, answers: objVal.map(answer => ({ answer }))}
:
{ id, answers: [{answer: objVal }] }
}
function formatObject(obj){
return Object.keys(obj).map((k, i) => answerMapper(obj[k], i+1));
}
const result = inputData.map(obj => formatObject(obj));
// remove flatMap if your inputData has more than one entry
console.log(result.flatMap(x => x));
map over the first element of the data with Object.entries, grab the key and value, create a new answers array and return a new object.
const data = [{
"q1": "5",
"q2": [
"13",
"12",
],
"q3": "test",
}];
const out = Object.entries(data[0]).map(obj => {
const [ key, value ] = obj;
const id = Number(key[1]);
// If the the value is an array
// return a new array of mapped data
// Otherwise return an array containing
// one object
const answers = Array.isArray(value)
? value.map(el => ({ answer: el }))
: [{ answer: value }];
// Return the new object
return { id, answers };
});
console.log(out);
lets create a pure function which accepts the object in the array like so
const processObject = obj => Object.keys(obj).map(id => {
const answer = obj[id];
const answers = Array.isArray(answer) ? answer : [answer]
const answerObjectArray = answers.map(ans => ({
answer: ans
}));
return {
id: +id.substring(1),
answers: answerObjectArray
}
});
const dataArray = [{
"q1": "5",
"q2": [
"13",
"12",
],
"q3": "test",
}];
const output = processObject(dataArray[0]);
console.log(output);

Determine if array element represents an object or a value

From a JSON object (containing stock data), I want to add certain elements to an array (in Google Sheets script editor):
var quote = JSON.parse(response.getContentText());
// Example of what quote object looks like:
{
"quoteSummary": {
"result": [
{
"Profile": {
"sector": "Technology",
"website": "www.test.com"
},
"Owners": [
{
"name": "Eric",
"age": "28"
},
{
"name": "Susan",
"age": "44"
}
],
"Profit": 100,
"Assets": 7000
}
]
}
}
Here is my current approach to read only some specific values:
var arr = [];
arr.push(quote.quoteSummary.result[0].Profile.sector); // Technology
arr.push(quote.quoteSummary.result[0].Owners[1].name); // Susan
arr.push(quote.quoteSummary.result[0].Profit); // 100
But since there are many specific properties to read, I'd like to use a loop:
var quote = JSON.parse(response.getContentText());
var arr = [];
var el = [
['Profile', 'sector'],
['Owners[1]', 'name'],
['Profit']
];
for (i = 0; i < el.length; i++)
{
if (quote.quoteSummary.result[0][el[i][0]][el[i][1]] !== undefined)
{
arr.push(quote.quoteSummary.result[0][el[i][0]][el[i][1]].value);
}
}
/*
Expected output (if I would loop through arr):
Technology
Susan
100
*/
The point is that different stocks, will have different properties. So el might define some non-existing elements or properties. Assume (in a bit of an other way of defining el -- as I wrote, I'm plexible here.. perhaps the paths are the easiest):
var el = [
'Profile.website',
'Profile.name',
'Assets'
]
/*
Expected output:
www.test.com
<----- "name" doesn't exist!
7000
Notice that in this example, there is no property "name" in Profile,
so I'd like to add an empty element to arr
*/
But this does not work. What is a generic loop that accomplishes what I'm trying to do here? The array defining what I want can also be constructed differently if that helps. But the point is that I don't end up with a script like:
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
arr.push(quote.quoteSummary.result[0].Profile.something);
I recommend you use variable-length chains of property names. Each name in a given chain represents a deeper property. You can "dive" into an object through an arbitrary number of property names with code like this:
let dive = (obj, propertyNames) => {
for (let pn of propertyNames) obj = obj[pn];
return obj;
};
Now you can say:
let dive = (obj, propertyNames) => {
for (let pn of propertyNames) obj = obj[pn];
return obj;
};
let quote = {
quoteSummary: {
result: [
{
Profile: {
sector: 'Technology',
website: 'www.test.com'
},
Owners: [
{
name: 'Eric',
age: '28'
},
{
name: 'Susan',
age: '44'
}
],
Profit: 100,
Assets: 7000
}
]
}
};
// Here are the "variable-length property chains":
let el = [
[ 'Profile', 'sector' ],
[ 'Owners', 1, 'name' ],
[ 'Profit' ]
];
// Here's how to combine `el`, `dive`, and your `quote` data to get a result:
let arr = el.map(propertyNames => dive(quote.quoteSummary.result[0], propertyNames));
console.log(arr);
You could even replace dive with Array.prototype.reduce, if you'd like to stay functional but avoid the function definition:
dive(someObj, propertyNames);
is equivalent to
propertyNames.reduce((obj, propName) => obj[propName], someObj);
Note the above code all assumes that a property exists for each term in the property chain (except the final property name, which may resolve to undefined without causing any errors). If some cases may have the, e.g., Profile key undefined or null you'll need to write some kind of if (propertyDoesntExist) / else statement which describes how to deal with missing properties.
For example you could modify dive to handle non-existent properties:
let dive = (obj, propertyNames, valueIfMissing=null) => {
for (let pn of propertyNames) {
// Intentional use of loose `==` operator!
if (obj == null) return valueIfMissing;
obj = obj[pn];
}
return obj;
};
This means that:
dive({ a: 1, b: 2, c: 3 }, [ 'd' ]) === null;
But we can substitute any default return value:
dive({ a: 1, b: 2, c: 3 }, [ 'd' ], 'ddd') === 'ddd';
Note this works at any depth:
dive({ a: { a: 1 }, b: { b: 2 }, c: { c: 3 }, d: null }, [ 'd', 'd' ]) === null;
dive({ a: { a: 1 }, b: { b: 2 }, c: { c: 3 }, d: null }, [ 'd', 'd' ], 'ddd') === 'ddd';
You should be able to do this:
if(y.value){
arr.push(y.value);
} else {
arr.push(y);
}
However, this will break if y.value happens to be something like 0, false, etc.
If this is the case you can do this:
if(y.hasOwnProperty("value")){
arr.push(y.value);
} else {
arr.push(y);
}
Based on the comment:
if (quote.quoteSummary.result[0][el[i][0]].hasOwnProperty("value")) {
arr.push(quote.quoteSummary.result[0][el[i][0]].value);
} else {
arr.push(quote.quoteSummary.result[0][el[i][0]]);
}

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);

How to get one json object format from another JSON format

Maybe this question has already been asked and answered somewhere but after searching for more than 3 hrs I'm asking this question.
Below is my JSON data
var my_data = [
{
"TempRture_qc": 4,
"VoltAGE": 44.09722,
"TempRture": 22.32,
"VoltAGE_qc": 55,
"_time": "2018-08-07T03:39:29.001Z"
},
{
"TempRture_qc": 2,
"VoltAGE": 42.09722,
"TempRture": 22.12,
"VoltAGE_qc": 0,
"_time": "2018-08-07T03:39:30.006Z"
},
{
"TempRture_qc": 1,
"VoltAGE": 43.09722,
"TempRture": 22.82,
"VoltAGE_qc": 0,
"_time": "2018-08-07T03:39:31.009Z"
}
];
desired output i need
[
{
"name": "TempRture_qc",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":4},
{"name":"2018-08-07T03:39:30.006Z","y":2},
{"name":"2018-08-07T03:39:33.017Z","y":1}
]
},
{
"name": "VoltAGE",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":44.09722},
{"name":"2018-08-07T03:39:30.006Z","y":42.09722},
{"name":"2018-08-07T03:39:33.017Z","y":43.09722}
]
},
{
"name": "TempRture",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":22.32},
{"name":"2018-08-07T03:39:30.006Z","y":22.12},
{"name":"2018-08-07T03:39:33.017Z","y":22.82}
]
},
{
"name": "VoltAGE_qc",
"data": [
{"name":"2018-08-07T03:39:29.001Z","y":55},
{"name":"2018-08-07T03:39:30.006Z","y":0},
{"name":"2018-08-07T03:39:33.017Z","y":0}
]
}
]
for getting this above output i have tried below code.
var accounting = [];
var fieldName = {};
for (var x in obj){
var mykey = Object.keys(obj[x]);
for (var mk in mykey){
if(mykey[mk]=='VoltAGE'){
fieldName.name = mykey[mk];
// accounting.push({
// "name":mykey[mk]
// })
}
if(mykey[mk]=='TempRture'){
fieldName.name = mykey[mk];
}
// console.log(mykey[mk]); //to get the key name
}
accounting.push({
"name" : obj[x]._time,
"y" : obj[x][employees.name],
})
fieldName.data = accounting;
}
console.log(fieldName );
by doing this what I'm getting is below JSON
{ name: 'TempRture',
data:
[ { name: '2018-08-07T03:39:29.001Z', y: 22.32 },
{ name: '2018-08-07T03:39:32.014Z', y: 22.12 },
{ name: '2018-08-07T03:39:33.017Z', y: 22.82 } ] }
I'm not able to understand how I will get the data in one JSON object.
For a solution with low time complexity, try .reduceing into an object indexed by keys of the inner object, creating a { name, data: [] } at that key in the accumulator if it doesn't exist there yet. Then, push to the data array, and get the values of the whole object:
var my_data=[{"TempRture_qc":4,"VoltAGE":44.09722,"TempRture":22.32,"VoltAGE_qc":55,"_time":"2018-08-07T03:39:29.001Z"},{"TempRture_qc":2,"VoltAGE":42.09722,"TempRture":22.12,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:30.006Z"},{"TempRture_qc":1,"VoltAGE":43.09722,"TempRture":22.82,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:31.009Z"}]
console.log(Object.values(
my_data.reduce((a, { _time, ...obj }) => {
Object.entries(obj).forEach(([name, val]) => {
if (!a[name]) a[name] = { name, data: [] };
a[name].data.push({ name: _time, y: val });
});
return a;
}, {})
));
var my_data=[{"TempRture_qc":4,"VoltAGE":44.09722,"TempRture":22.32,"VoltAGE_qc":55,"_time":"2018-08-07T03:39:29.001Z"},{"TempRture_qc":2,"VoltAGE":42.09722,"TempRture":22.12,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:30.006Z"},{"TempRture_qc":1,"VoltAGE":43.09722,"TempRture":22.82,"VoltAGE_qc":0,"_time":"2018-08-07T03:39:31.009Z"}]
var keys = Object.keys(my_data[0])
var result= [];
for(i = 0; i<keys.length-1; i++) {
var obj = {name: keys[i],data: []}
obj.data = my_data.map(val=>({name: val["_time"], y: val[keys[i]]}));
result.push(obj);
}
console.log(result)
An understandable answer with map, findIndex and forEach functions will be
var my_data = [{ "TempRture_qc": 4, "VoltAGE": 44.09722, "TempRture": 22.32, "VoltAGE_qc": 55, "_time": "2018-08-07T03:39:29.001Z" }, { "TempRture_qc": 2, "VoltAGE": 42.09722, "TempRture": 22.12, "VoltAGE_qc": 0, "_time": "2018-08-07T03:39:30.006Z" }, { "TempRture_qc": 1, "VoltAGE": 43.09722, "TempRture": 22.82, "VoltAGE_qc": 0, "_time": "2018-08-07T03:39:31.009Z" } ],
result = [];
my_data.map(itm => {
let keys = Object.keys(itm);
keys.forEach(iitt => {
if (iitt != '_time') {
let index = result.findIndex(ii => {
return ii.name == iitt;
})
if (index == -1) {
result.push({
name: iitt,
data: []
});
result[result.length - 1].data.push({
name: itm["_time"],
y: itm[iitt]
})
} else {
result[index].data.push({
name: itm["_time"],
y: itm[iitt]
});
}
}
})
})
console.log(result)

Accessing nodes by ID

this might be a daft question but...
I'm just jquery to access an object using:
obj["surveySpec"]["3"]["Survey"]["5"]["description"];
the problem is that depending on the results it can be a different length, what does stay the same is the id of 42333
Is there a way to search for that ID and bring back the values?
I tried
var result2 = $.grep(obj2, function(e){ return e.id === 42333; });
but that didn't work
The object is:
Object
Object
id:1
registration:"NA123"
serviceVersion:"V2"
surveySpec:Array[7]
0:Object
1:Object
2:Object
3:Object
Survey:Array[15]
0:Object
1:Object
2:Object
3:Object
4:Object
5:Object
description:"survey results, 5, 2 and 3"
id:42333
items:Array[3]
name:"survey results"
value:"standard"
var test = {
id: 1,
items: [
{
id: 11,
description: "three",
surveys: [
{
id: 121,
description: "one"
},
{
id: 122,
description: "two"
}
]
},
{
id: 12,
description: "seven"
},
{
id: 13,
description: "four",
surveys: [
{
id: 131,
description: "five"
},
{
id: 132,
description: "six"
}
]
}
]
};
function findById(obj, id) {
if (obj) {
if (obj.id == id)
return obj;
for(var key in obj) {
if ((typeof obj[key]).toLowerCase() != "string" &&
(typeof obj[key]).toLowerCase() != "number") {
var result = findById(obj[key], id);
if (result)
return result;
}
}
}
return null;
}
var result = findById(test, 131);
console.log("result:");
console.log(result);
var myVar = '';
$.each(obj["surveySpec"],function(index,object){
$.each(obj["survey"],function(ind,innerObject){
if(innerOject.id === 42333){
myVar = innerObject.description;
return false;}
});
});
looks like this might be what you are looking for.

Categories

Resources