Convert JSON based on a key value using Javascript - javascript

I get some records from a database in the following JSON format:
data: [{
"y": "0.652008685",
"x": "-0.13926217",
"geneName": "ADAMTS2",
"cond": "Cell"
},
{
"y": "-3.486001",
"x": "-2.295312",
"geneName": "IGSF22",
"cond": "ECM"
},
{
"y": "-3.597706",
"x": "-2.672138",
"geneName": "OXA1L",
"cond": "ECM"
}
]
I would like to transform the above result and group the y,x and geneName name/value pairs based on the cond key using JavaScript.
The result I'd like is shown below:
series: [{
name: 'Cell',
color: '#fff',
data: [{
"name": "ADAMTS2",
"x": -0.13926217,
"y": 0.652008685
}]
},
{
name: 'ECM',
color: '#000',
data: [{
"name": "IGSF22",
"x": -2.295312,
"y": -3.486001
},
{
"name": "OXA1L",
"x": -2.672138,
"y": -3.597706
}
]
}
]
For every different grouping I'd like to add an extra name/value pair color.
Is there any smart and quick way to do it using JavaScript by avoiding the naive approach of the for loops?
Thanks in advance

You could use Array.prototype.reduce to group common objects by object.cond, like so:
var data = [{
"y": "0.652008685",
"x": "-0.13926217",
"geneName": "ADAMTS2",
"cond": "Cell"
},
{
"y": "-3.486001",
"x": "-2.295312",
"geneName": "IGSF22",
"cond": "ECM"
},
{
"y": "-3.597706",
"x": "-2.672138",
"geneName": "OXA1L",
"cond": "ECM"
}
];
var dataMap = data.reduce((result, item) => {
// create root-level object for a name if it doesn't already exist
if (!result[item.cond]) {
result[item.cond] = {
name: item.cond,
color: ''/*not sure what your logic is here*/,
data: []
}
}
// add current item to the root-level object data
result[item.cond].data.push({
name: item.geneName,
x: parseFloat(item.x),
y: parseFloat(item.y)
});
return result;
}, {/*resulting map*/});
// last step is to get an array of the values since that's the desired format
data = Object.values(dataMap);
document.getElementById('result').innerHTML = JSON.stringify(data, null, 4);
<pre id="result"></pre>

You can use .reduce here. Make a object whose key is basically cond and then from that object transform a array using .map.
var x = {
data: [{
"y": "0.652008685",
"x": "-0.13926217",
"geneName": "ADAMTS2",
"cond": "Cell"
},
{
"y": "-3.486001",
"x": "-2.295312",
"geneName": "IGSF22",
"cond": "ECM"
},
{
"y": "-3.597706",
"x": "-2.672138",
"geneName": "OXA1L",
"cond": "ECM"
}
]
};
x.data = Object.entries(x.data.reduce((acc, el) => {
let cond = el.cond;
delete el.cond;
if(acc.hasOwnProperty(cond)){
acc[cond].data.push(el);
}
else{
acc[cond] = {};
acc[cond].data = [el];
}
return acc;
}, {})).map(el => {
return {name: el[0], data: el[1].data};
});
console.log(x);

data = [{
"y": "0.652008685",
"x": "-0.13926217",
"geneName": "ADAMTS2",
"cond": "Cell"
},
{
"y": "-3.486001",
"x": "-2.295312",
"geneName": "IGSF22",
"cond": "ECM"
},
{
"y": "-3.597706",
"x": "-2.672138",
"geneName": "OXA1L",
"cond": "ECM"
}
]
series = []
definedName = []
data.forEach(function(item) {
var ind = definedName.findIndex((element) => {
return element == item.cond;
});
if (ind === -1) {
obj = {
name: item.cond,
color: '#fff',
data: [{
"name": item.geneName,
"x": item.x,
"y": item.y
}]
}
definedName.push(item.cond)
series.push(obj)
} else {
obj = {
"name": item.geneName,
"x": item.x,
"y": item.y
}
series[ind]["data"].push(obj)
}
});
console.log(series)

Related

Merge objects and get max value for each property

I have to reduce an object of objects and get just 1 object with the max values for each property, for example
My input object is:
input: {
"2.0": {
"prop1": {
"x": 88,
"y": 231
},
"prop2": {
"x": 79,
"y": 175
},
"prop3": {
"x": -3,
"y": 22
},
"prop4": {
"x": -2,
"y": 2
}
},
"1.0": {
"prop1": {
"x": 35,
"y": 324
},
"prop2": {
"x": 99,
"y": 509
},
"prop3": {
"x": 3,
"y": 14
},
"prop4": {
"x": 4,
"y": 25
}
}
}
and the final object must to have:
output:{
"prop1": {
"x": 88, //because is max on 2.0 object
"y": 324 //because is max on 1.0 object
},
"prop2": {
"x": 99,
"y": 509
},
"prop3": {
"x": 3,
"y": 22
},
"prop4": {
"x": 4,
"y": 25
},
}
The idea is to get for each property between multiple objects the max value between them and get 1 final object with all properties with the max value between all objects. Thanks in advance
Currently I trying with a reduce and then a foreach but I cant get the final result correctly.
Object.values(input).reduce((highestValues, objData) => {
Object.entries(objData).forEach(([key, value]) => {
const highest = highestValues[key];
if (highest === undefined || highest > value) {
highestValues[key] = value
}
})
return highestValues
}, {});
You could do it like this:
const data = { "2.0": {
"prop1": {
"x": 88,
"y": 231
},
"prop2": {
"x": 79,
"y": 175
},
"prop3": {
"x": -3,
"y": 22
},
"prop4": {
"x": -2,
"y": 2
}
},
"1.0": {
"prop1": {
"x": 35,
"y": 324
},
"prop2": {
"x": 99,
"y": 509
},
"prop3": {
"x": 3,
"y": 14
},
"prop4": {
"x": 4,
"y": 25
}
}
}
console.log(Object.values(data).reduce((carry, current) => {
Object.entries(current).forEach(([key, value]) => {
Object.entries(value).forEach(([k,v]) => {
if (!carry[key]) {
carry[key] = {}
}
carry[key][k] = Math.max(carry[key][k], v);
});
});
return carry;
}));

AWS recognition face API: Crop teeth section (mouth) from face

I'm cropping teeth section (mouth) from face based on x,y co-ordinates received from AWS recognition face API
this code is working and cropping the teeth section like
but I need only teeth section to be cropped.
AWS recognition API image response
[
{
"BoundingBox": {
"Width": 0.4604368805885315,
"Height": 0.7760819792747498,
"Left": 0.28602713346481323,
"Top": 0.07381705939769745
},
"AgeRange": {
"Low": 48,
"High": 66
},
"Smile": {
"Value": true,
"Confidence": 99.91497802734375
},
"Eyeglasses": {
"Value": false,
"Confidence": 98.94174194335938
},
"Sunglasses": {
"Value": false,
"Confidence": 99.84471130371094
},
"Gender": {
"Value": "Male",
"Confidence": 99.57334899902344
},
"Beard": {
"Value": false,
"Confidence": 73.63420867919922
},
"Mustache": {
"Value": false,
"Confidence": 96.08769226074219
},
"EyesOpen": {
"Value": true,
"Confidence": 98.94685363769531
},
"MouthOpen": {
"Value": true,
"Confidence": 99.7721939086914
},
"Emotions": [
{
"Type": "HAPPY",
"Confidence": 99.75701904296875
},
{
"Type": "SURPRISED",
"Confidence": 0.10713297128677368
},
{
"Type": "CONFUSED",
"Confidence": 0.056786004453897476
},
{
"Type": "CALM",
"Confidence": 0.02734198607504368
},
{
"Type": "ANGRY",
"Confidence": 0.020567195490002632
},
{
"Type": "DISGUSTED",
"Confidence": 0.01198340579867363
},
{
"Type": "SAD",
"Confidence": 0.011844608001410961
},
{
"Type": "FEAR",
"Confidence": 0.007329543586820364
}
],
"Landmarks": [
{
"Type": "eyeLeft",
"X": 0.4020455777645111,
"Y": 0.3627050220966339
},
{
"Type": "eyeRight",
"X": 0.6262026429176331,
"Y": 0.379489928483963
},
{
"Type": "mouthLeft",
"X": 0.40419745445251465,
"Y": 0.6104526519775391
},
{
"Type": "mouthRight",
"X": 0.5907381772994995,
"Y": 0.6247860193252563
},
{
"Type": "nose",
"X": 0.49532997608184814,
"Y": 0.48828810453414917
},
{
"Type": "leftEyeBrowLeft",
"X": 0.32399997115135193,
"Y": 0.3045051097869873
},
{
"Type": "leftEyeBrowRight",
"X": 0.38662829995155334,
"Y": 0.27300384640693665
},
{
"Type": "leftEyeBrowUp",
"X": 0.4492948651313782,
"Y": 0.2880849540233612
},
{
"Type": "rightEyeBrowLeft",
"X": 0.578127920627594,
"Y": 0.29742100834846497
},
{
"Type": "rightEyeBrowRight",
"X": 0.6459962725639343,
"Y": 0.29183030128479004
},
{
"Type": "rightEyeBrowUp",
"X": 0.7144292593002319,
"Y": 0.3330812454223633
},
{
"Type": "leftEyeLeft",
"X": 0.3629233241081238,
"Y": 0.3603385388851166
},
{
"Type": "leftEyeRight",
"X": 0.4457237124443054,
"Y": 0.36826738715171814
},
{
"Type": "leftEyeUp",
"X": 0.4013364613056183,
"Y": 0.3494759500026703
},
{
"Type": "leftEyeDown",
"X": 0.40179359912872314,
"Y": 0.37347349524497986
},
{
"Type": "rightEyeLeft",
"X": 0.5811655521392822,
"Y": 0.3783351182937622
},
{
"Type": "rightEyeRight",
"X": 0.6668664813041687,
"Y": 0.38298410177230835
},
{
"Type": "rightEyeUp",
"X": 0.6265660524368286,
"Y": 0.36624279618263245
},
{
"Type": "rightEyeDown",
"X": 0.6238686442375183,
"Y": 0.39007559418678284
},
{
"Type": "noseLeft",
"X": 0.4562915861606598,
"Y": 0.5203639268875122
},
{
"Type": "noseRight",
"X": 0.5394821166992188,
"Y": 0.5265129804611206
},
{
"Type": "mouthUp",
"X": 0.4932428300380707,
"Y": 0.5806143283843994
},
{
"Type": "mouthDown",
"X": 0.48947831988334656,
"Y": 0.6564671397209167
},
{
"Type": "leftPupil",
"X": 0.4020455777645111,
"Y": 0.3627050220966339
},
{
"Type": "rightPupil",
"X": 0.6262026429176331,
"Y": 0.379489928483963
},
{
"Type": "upperJawlineLeft",
"X": 0.28082960844039917,
"Y": 0.37847602367401123
},
{
"Type": "midJawlineLeft",
"X": 0.3077985942363739,
"Y": 0.6443988680839539
},
{
"Type": "chinBottom",
"X": 0.48529136180877686,
"Y": 0.7894702553749084
},
{
"Type": "midJawlineRight",
"X": 0.7061411738395691,
"Y": 0.6732134819030762
},
{
"Type": "upperJawlineRight",
"X": 0.77140212059021,
"Y": 0.4138971269130707
}
],
"Pose": {
"Roll": 3.0064163208007812,
"Yaw": -2.569990634918213,
"Pitch": 8.883845329284668
},
"Quality": {
"Brightness": 76.55046844482422,
"Sharpness": 94.08262634277344
},
"Confidence": 99.99818420410156
}
]
Node Js code for crop using gm ImageMagick library
const init = async () => {
try {
console.info("Process Started");
const size = await getImageSize("passport-photo.jpeg");
console.info("get Image Size: ", size);
const faceDetails = await getFaceDetailsFromImage();
// Uploded image width height
const imageWidth = size.width;
const imageHeight = size.height;
// Face detail width height
const faceDetailWidth = Math.round(faceDetails[0].BoundingBox.Width * imageWidth);
const faceDetailHeight = Math.round(faceDetails[0].BoundingBox.Height * imageHeight);
// Coordinates for the mouth
const faceDetailMouthLeft = faceDetails[0].Landmarks.filter(o => o.Type === "mouthLeft");
const faceDetailMouthRight = faceDetails[0].Landmarks.filter(o => o.Type === "mouthRight");
const faceDetailMouthUp = faceDetails[0].Landmarks.filter(o => o.Type === "mouthUp");
const faceDetailMouthDown = faceDetails[0].Landmarks.filter(o => o.Type === "mouthDown");
// Find x and y point from where the cropping needs to be started
const xPoint = Math.round(faceDetailMouthLeft[0].X * imageWidth);
const yPoint = Math.round(faceDetailMouthUp[0].Y * imageHeight);
// Width height for which image needs to be cut from start index
const width = ((faceDetailMouthRight[0].X - faceDetailMouthLeft[0].X) * imageWidth)
const height = ((faceDetailMouthDown[0].Y - faceDetailMouthUp[0].Y) * imageHeight)
console.log("xPoint:" + xPoint + ", yPoint:" + yPoint + ", faceDetailWidth:" + faceDetailWidth + ", faceDetailHeight:" + faceDetailHeight)
gm('passport-photo.jpeg')
// Invoke crop function
.crop(width, height, xPoint, yPoint, true)
// Process and Write the image
.write("crop5.png", function (err) {
console.error(err);
if (!err) console.log('done');
});
} catch (error){
console.error(error);
}
}
init();
original image
Your calculations for the mouth co-ordinates appear to be correct.
However, I see you are using:
.crop(width, height, xPoint, yPoint, true)
As you say, this "accepts the parameter as a percentage value", which probably isn't what you want.

Sorting object in JS by one of the keys in each element

I have an object in JS structured as follows:
[{
"x": 2.31,
"y": 0.538
},
{
"x": 7.07,
"y": 0.469
},
{
"x": 6.02,
"y": 0.469
},
{
"x": 2.18,
"y": 0.458
}]
I need to sort by one of the keys in each element (sort by x). The result would look like this:
[{
"x": 2.18,
"y": 0.458
},
{
"x": 2.31,
"y": 0.538
},
{
"x": 6.02,
"y": 0.469
},
{
"x": 7.07,
"y": 0.469
}]
The following approach doesn't work with the above structure:
var sorted = [];
for(var key in dict) {
sorted[sorted.length] = key;
}
sorted.sort();
Nor does the following:
function sortObject(o) {
return Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {});
}
Implement a custom sort method.
var arr = [{ "x": 2.31, "y": 0.538 }, { "x": 7.07, "y": 0.469 }, { "x": 6.02, "y": 0.469 }, { "x": 2.18, "y": 0.458 }]
arr.sort((a,b) => a.x - b.x)
console.log(arr);
Yes, you can sort the key value of the object by comparing the key's value using parseFloat.
var coordinates=[{
"x": 2.31,
"y": 0.538
},
{
"x": 7.07,
"y": 0.469
},
{
"x": 6.02,
"y": 0.469
},
{
"x": 2.18,
"y": 0.458
}]
var sortedKey=coordinates.sort(function(a, b) {
return parseFloat(a.x) - parseFloat(b.x);
});
console.log(sortedKey);
You can use lodash. https://lodash.com/docs/4.17.4#sortBy
lodash is a modern JavaScript utility library delivering modularity, performance & extras.
Demo: http://jsfiddle.net/e2ccmbhh
let arr = [{
"x": 2.31,
"y": 0.538
},
{
"x": 7.07,
"y": 0.469
},
{
"x": 6.02,
"y": 0.469
},
{
"x": 2.18,
"y": 0.458
}]
let sortedArr = _.sortBy(arr, 'x');
You can use Javascript builtin sort() method to do that.
var myList = [{
"x": 2.31,
"y": 0.538
},
{
"x": 7.07,
"y": 0.469
},
{
"x": 6.02,
"y": 0.469
},
{
"x": 2.18,
"y": 0.458
}];
var sortedList = myList.sort(function(a, b){
return a.x - b.x;
});
console.log(sortedList);
What you have do here is implement a custom sort method for comparison between the elements in your array.
Try this out.
const array = [{
"x": 2.31,
"y": 0.538
},
{
"x": 7.07,
"y": 0.469
},
{
"x": 6.02,
"y": 0.469
},
{
"x": 2.18,
"y": 0.458
}];
array.sort((obj1, obj2) => {
return obj1.x - obj2.x;
});

Applying a method to JavaScript object on the fly

I have a dynamically loaded object for which the print of JSON.stringify() in the console looks like this:
var data = [
{
"attributes": {
"OBJECTID": 1046
},
"geometry": {
"x": -9814734.1764,
"y": 5130578.545900002
}
},
{
"attributes": {
"OBJECTID": 1051
},
"geometry": {
"x": -9814335.3286,
"y": 5130497.9344
}
},
{
"attributes": {
"OBJECTID": 1052
},
"geometry": {
"x": -9814639.1784,
"y": 5130583.1822
}
},
{
"attributes": {
"OBJECTID": 1053
},
"geometry": {
"x": -9814496.7964,
"y": 5130560.822300002
}
}
];
How can I apply .toFixed(2) function to each of X and Y in geometry nodes on the fly?
You need to use the map function:
const formattedData = data.map(d => {
d.geometry.x = parseFloat(d.geometry.x).toFixed(2);
d.geometry.y = parseFloat(d.geometry.y).toFixed(2);
return d;
})
Feel free to change the property name (x -> xFormatted) if you don't wish to override the original data.
Use map
data = data.map( function(s){
s.geometry.x = s.geometry.x.toFixed(2);
s.geometry.y = s.geometry.y.toFixed(2);
return s;
})
Edit
Or with forEach
data.forEach( function(s){
s.geometry.x = s.geometry.x.toFixed(2);
s.geometry.y = s.geometry.y.toFixed(2);
})
Try this
//Your Data
var data = [
{
"attributes": {
"OBJECTID": 1046
},
"geometry": {
"x": -9814734.1764,
"y": 5130578.545900002
}
},
{
"attributes": {
"OBJECTID": 1051
},
"geometry": {
"x": -9814335.3286,
"y": 5130497.9344
}
},
{
"attributes": {
"OBJECTID": 1052
},
"geometry": {
"x": -9814639.1784,
"y": 5130583.1822
}
},
{
"attributes": {
"OBJECTID": 1053
},
"geometry": {
"x": -9814496.7964,
"y": 5130560.822300002
}
}
];
//Updating data
data.forEach(function(item,index){
item["geometry"]["x"]=item["geometry"]["x"].toFixed(2);
item["geometry"]["y"]=item["geometry"]["y"].toFixed(2);
})
console.log(JSON.stringify(data))
Just iterate using the forEach function. Also make sure to parse the value using parseFloat before calling the toFixed function.
data.forEach(entry => {
entry.geometry.x = parseFloat(entry.geometry.x).toFixed(2);
entry.geometry.y = parseFloat(entry.geometry.y).toFixed(2);
});

How to push json data in javascript?

I have a json file, the file have data like this format :
{
"rigidBodies": [
{
"name": "ball1.png", "imagePath": "ball1.png", "origin": {"x": 0, "y": 0},
"polygons": [
[
{"x": 0.16999998688697815, "y": 0.5724999904632568},
{"x": 0.16749995946884155, "y": 0.5324999690055847},
{"x": 0.16999998688697815, "y": 0.45250001549720764}
],
[
{"x": 0.16999998688697815, "y": 0.45250001549720764},
{"x": 0.16749995946884155, "y": 0.375},
{"x": 0.2199999988079071, "y": 0.3725000023841858}
]
]
}
]
}
I want to push the data in an Array so I have tried this way and it says error,
var poly = new Array();
// note : parsing json
$.getJSON('my_assets/addPhysics/testPhysics.json', function(data) {
//do stuff with your data here
$.each(data, function(i, item) {
// for(var i=0;i<item[0].length;i++){
poly.push(item[0][i].x,item[0][i].y);
//}
});
});
data is an object, the array you want to loop through is in the polygons property inside the rigidBodies array. You need to do:
var data = {
"rigidBodies": [{
"name": "ball1.png",
"imagePath": "ball1.png",
"origin": {
"x": 0,
"y": 0
},
"polygons": [
[{
"x": 0.16999998688697815,
"y": 0.5724999904632568
}, {
"x": 0.16749995946884155,
"y": 0.5324999690055847
}, {
"x": 0.16999998688697815,
"y": 0.45250001549720764
}],
[{
"x": 0.16999998688697815,
"y": 0.45250001549720764
}, {
"x": 0.16749995946884155,
"y": 0.375
}, {
"x": 0.2199999988079071,
"y": 0.3725000023841858
}]
]
}]
}
var poly = [];
$.each(data.rigidBodies, function(i, body) {
$.each(body.polygons, function(j, polygon) {
$.each(polygon, function(k, coords) {
poly.push([coords.x, coords.y]);
});
});
});
document.getElementById("output").innerHTML = JSON.stringify(poly);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
You should try this
poly.push([item[0][i].x,item[0][i].y]);
So poly[0][0] is X
and poly [0][1] is Y

Categories

Resources