Merge objects and get max value for each property - javascript

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

Related

how to make polygons made on my image clickable using canvas js?

var b = {
"vertices": [
[{ "x": 15, "y": 5 }, { "x": 28, "y": 2 }, { "x": 37, "y": 49 }, { "x": 24, "y": 51 }],
[{ "x": 106, "y": 5 }, { "x": 252, "y": 3 }, { "x": 252, "y": 36 }, { "x": 106, "y": 38 }],
[{ "x": 16, "y": 40 }, { "x": 296, "y": 41 }, { "x": 296, "y": 100 }, { "x": 16, "y": 99 }],
[{ "x": 26, "y": 123 }, { "x": 255, "y": 124 }, { "x": 255, "y": 239 }, { "x": 26, "y": 238 }],
[{ "x": 106, "y": 376 }, { "x": 255, "y": 375 }, { "x": 255, "y": 393 }, { "x": 106, "y": 394 }]]
};
Polygon draw function for drawing the above coordinates in canvas js:
function drawpolygon() {
for (i = 0; i < ar.vertices.length; i++) {
for (j = 0; j <= 3; j++) {
cx.beginPath();
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
cx.lineTo(ar.vertices[i][1].x, ar.vertices[i][1].y);
cx.lineTo(ar.vertices[i][2].x, ar.vertices[i][2].y);
cx.lineTo(ar.vertices[i][3].x, ar.vertices[i][3].y);
if (j == 3) {
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
}
cx.strokeStyle = "red";
cx.lineWidth = "1.5";
cx.stroke();
cx.closePath();
}
}
}
i have drawn the polygons using the canvas js. How to make these clickable? Hitregion is outdated..
You can leverage Canvas​Rendering​Context2D.isPoint​InPath(). It will allow you to determine if a given point is within either the "current" stateful path or if a point is in a Path2D object if you use those instead.
Try clicking within the rendered polygons below.
const canvas = document.getElementById("canvas");
const cx = canvas.getContext("2d");
var ar = {
"vertices": [
[{ "x": 15, "y": 5 }, { "x": 28, "y": 2 }, { "x": 37, "y": 49 }, { "x": 24, "y": 51 }],
[{ "x": 106, "y": 5 }, { "x": 252, "y": 3 }, { "x": 252, "y": 36 }, { "x": 106, "y": 38 }],
[{ "x": 16, "y": 40 }, { "x": 296, "y": 41 }, { "x": 296, "y": 100 }, { "x": 16, "y": 99 }],
[{ "x": 26, "y": 123 }, { "x": 255, "y": 124 }, { "x": 255, "y": 239 }, { "x": 26, "y": 238 }],
[{ "x": 106, "y": 376 }, { "x": 255, "y": 375 }, { "x": 255, "y": 393 }, { "x": 106, "y": 394 }]]
};
function drawpolygon(e) {
let x, y;
// Only try to hit detect if there was a click
if (e) {
// Localize the click to within the canvas
const {clientX, clientY, currentTarget} = e;
const {left, top} = currentTarget.getBoundingClientRect();
x = clientX - left;
y = clientY - top;
}
// Clear the canvas
cx.clearRect(0, 0, canvas.width, canvas.height);
// Iterate all the polygons
for (i = 0; i < ar.vertices.length; i++) {
for (j = 0; j <= 3; j++) {
cx.beginPath();
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
cx.lineTo(ar.vertices[i][1].x, ar.vertices[i][1].y);
cx.lineTo(ar.vertices[i][2].x, ar.vertices[i][2].y);
cx.lineTo(ar.vertices[i][3].x, ar.vertices[i][3].y);
if (j == 3) {
cx.lineTo(ar.vertices[i][0].x, ar.vertices[i][0].y);
}
cx.closePath();
// Paint green if the click was in the path, red otherwise
cx.strokeStyle = cx.isPointInPath(x, y) ? "green" : "red";
cx.lineWidth = "1.5";
cx.stroke();
}
}
}
// Draw immediately for reference
drawpolygon();
// Draw again whenever we click
canvas.addEventListener("click", drawpolygon);
<canvas id="canvas" width="512" height="512"></canvas>

Convert JSON based on a key value using 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)

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

How to remove double qoutes from json data

I am working on cordova. From a php script i have generated a json data. Below is my json data
"11111111": [
{ "x": "2016-01-25 12:58:52", "y": "25.22" },
{ "x": "2016-01-26 13:33:23", "y": "30.14" },
{ "x": "2016-01-27 13:49:18", "y": "35.58" },
{ "x": "2016-01-29 13:55:01", "y": "40.25" },
{ "x": "2016-01-30 14:00:15", "y": "47.25" },
{ "x": "2016-01-31 15:50:15", "y": "14.25" },
{ "x": "2016-02-01 16:16:15", "y": "20.25" },
{ "x": "2016-02-02 17:49:15", "y": "5.25" },
{ "x": "2016-02-03 18:20:15", "y": "77.25" },
{ "x": "2016-02-04 19:30:15", "y": "65.25" }
],
But i want to remove the double quotes from the y data i.e.
"11111111": [
{ "x": "2016-01-25 12:58:52", "y": 25.22 },
{ "x": "2016-01-26 13:33:23", "y": 30.14 },
{ "x": "2016-01-27 13:49:18", "y": 35.58 },
{ "x": "2016-01-29 13:55:01", "y": 40.25 },
{ "x": "2016-01-30 14:00:15", "y": 47.25 },
{ "x": "2016-01-31 15:50:15", "y": 14.25 },
{ "x": "2016-02-01 16:16:15", "y": 20.25 },
{ "x": "2016-02-02 17:49:15", "y": 5.25 },
{ "x": "2016-02-03 18:20:15", "y": 77.25 },
{ "x": "2016-02-04 19:30:15", "y": 65.25 }
],
Updated Code:
Below is my script from which i have generated json
if($result)
{
while($row = mysqli_fetch_array($result))
{
$serial = $row['Device_Serial_Number'];
$x = $row['Data_Datetime'];
$y = $row['Energy_kwh'];
if(!isset($data[$serial]))
{
$data[$serial] = [];
}
$data[$serial][] = ['x' => $x , 'y' => $y];
}
mysqli_free_result($result);
}
$json = json_encode($data, JSON_PRETTY_PRINT);
echo "var jsonData = " . $json;
I searched many articles but couldn't find any good solution
Any help would be highly appreciated
If you get a string back from a database or a $_POST value, you can cast it to float:
$data[$serial][] = ['x' => $x , 'y' => (float) $y];
When the you created the json data, $y is float data type, and when your php script generated the data you should make sure that the precision of the float data type not replaced by string
you can use option for json_encode
JSON_PRESERVE_ZERO_FRACTION
its different for each php version
you should check the manual
http://php.net/manual/en/json.constants.php
but it does not matter if setter getter in your cordova can handle it, you can cast to float when your app get data from your php script even if your script return it as string.
sorry for bad english

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