How to sum property in array of objects, based on a condition - javascript

I'm a junior Web Developer, looking for some guidance solving a problem. Please excuse me if I'm missing anything integral, as this my first time posting here.
I have an array of some data returned like so:
[
{x: Date(1234), y: 0}
{x: Date(1235), y: 0}
{x: Date(1236), y: 300}
{x: Date(1237), y: 300}
{x: Date(1238), y: 300}
{x: Date(1239), y: 300}
{x: Date(1240), y: 300}
{x: Date(1241), y: 0}
{x: Date(1242), y: 0}
{x: Date(1243), y: 0}
]
If possible, I'd like to return a new array in which all consecutive 'y' values > 0 are summed. In the new array, the summed value should be associated with the first 'x' value of the summed items, like so:
[
{x: Date(1234), y: 0}
{x: Date(1235), y: 0}
{x: Date(1236), y: 1500}
{x: Date(1241), y: 0}
{x: Date(1242), y: 0}
{x: Date(1243), y: 0}
]
I'm thinking this will likely involve 'reduce,' but I'm a little unsure how to proceed. Any help would be greatly appreciated.
Thanks in advance!

Using reduce, you could do something like this: https://jsbin.com/leladakiza/edit?js,console
var input = [
{x: Date(1234), y: 0},
{x: Date(1235), y: 0},
{x: Date(1236), y: 300},
{x: Date(1237), y: 300},
{x: Date(1238), y: 300},
{x: Date(1239), y: 300},
{x: Date(1240), y: 300},
{x: Date(1241), y: 0},
{x: Date(1242), y: 0},
{x: Date(1243), y: 0},
];
var output = input.reduce(function (acc, val) {
var lastIndex = acc.length - 1;
if (val.y <= 0 || lastIndex < 0 || acc[lastIndex].y <= 0) {
acc.push(val);
} else {
acc[lastIndex].y += val.y;
}
return acc;
}, []);

I think you can use a reduce function like this.
var arr = [{
x: Date(1234),
y: 0
},
{
x: Date(1235),
y: 0
},
{
x: Date(1236),
y: 300
},
{
x: Date(1237),
y: 300
},
{
x: Date(1238),
y: 300
},
{
x: Date(1239),
y: 300
},
{
x: Date(1240),
y: 300
},
{
x: Date(1241),
y: 0
},
{
x: Date(1242),
y: 0
},
{
x: Date(1243),
y: 0
}
];
var yGreaterThanZero = null;
var aggregated = arr.reduce(function(acc, cur) {
if (cur.y > 0) {
if (!yGreaterThanZero) {
acc.push(cur);
yGreaterThanZero = cur;
} else {
yGreaterThanZero.y += cur.y;
}
} else {
acc.push(cur);
}
return acc;
}, []);
console.log(aggregated);

This is a very crude logic. We start recording when a value greater than 0 is obtained and push it at the end of the recording (value less than 0)
var a = [
{x: Date(1234), y: 0},
{x: Date(1235), y: 0},
{x: Date(1236), y: 300},
{x: Date(1237), y: 300},
{x: Date(1238), y: 300},
{x: Date(1239), y: 300},
{x: Date(1240), y: 300},
{x: Date(1241), y: 0},
{x: Date(1242), y: 0},
{x: Date(1243), y: 0},
{x: Date(1244), y: 200},
{x: Date(1245), y: 200},
{x: Date(1246), y: 200},
{x: Date(1247), y: 200},
]
var newA = [];
var recording = false;
var temp = {}
a.forEach(item => {
if (item.y > 0) {
recording = true;
if (temp.y) {
if(!temp.x) temp.x = item.x;
temp.y = temp.y + item.y
} else {
temp = item;
}
} else {
if (recording) newA.push(temp)
recording = false;
temp = {};
newA.push(item);
}
})
if (recording) newA.push(temp)
console.log(newA)

Related

How to use array reduce to sort data

How tu use reduce array to sort entries date here:
const entries = [
{date: 'lu'},
{date: 'lu'},
{date: 'ma'},
{date: 'ma'}
]
where output count occurence of date
const data = [
{x: 'lu', y: 2},
{x: 'ma', y: 2},
{x: 'me', y: 0},
{x: 'je', y: 0},
{x: 've', y: 0},
{x: 'sa', y: 0},
{x: 'di', y: 0},
]
Thanks for help :)
Two nested forEach will do. Because you need to have the x an y values for each days even if it does not appear in the entries. So reduce won't do.
So you need to set a starter data array of objects for each days... Then loop the entries against every days.
const entries = [
{date: 'lu'},
{date: 'lu'},
{date: 'ma'},
{date: 'ma'}
]
const data = [
{x: 'lu', y: 0},
{x: 'ma', y: 0},
{x: 'me', y: 0},
{x: 'je', y: 0},
{x: 've', y: 0},
{x: 'sa', y: 0},
{x: 'di', y: 0},
]
entries.forEach(entry => {
data.forEach(d => {
if(d.x === entry.date){
d.y++
}
})
})
console.log(data)

Get the id of the nearest coordinate object

I am using the answer in the example to find the nearest object coordinate. How do I find the index of the nearest point from var points if e.g. the nearest point is {x: 12, y: 18}, then index = 1?
I want to avoid using an extra indexOf() if that step can be saved.The code is:
var points = [
{x: 10, y: 20},
{x: 12, y: 18},
{x: 20, y: 30},
{x: 5, y: 40},
{x: 100, y: 2}
];
function d(point) {
return Math.pow(point.x, 2) + Math.pow(point.y, 2);
}
var closest = points.slice(1).reduce(function(min, p) {
if (d(p) < min.d) min.point = p;
return min;
}, {point: points[0], d:d(points[0])}).point;
console.log(closest);
You could map the array to an array of objects first that also contain the index:
const points = [
{x: 10, y: 20},
{x: 12, y: 18},
{x: 20, y: 30},
{x: 5, y: 40},
{x: 100, y: 2}
];
const distance = (point) => {
return Math.pow(point.x, 2) + Math.pow(point.y, 2);
}
const result = points
.map((point, index) => ({ point, index }))
.reduce((a, b) => distance(a.point) < distance(b.point) ? a : b);
console.log(result);

How to update values not present in one array of objects from another array of objects?

I have two arrays of objects which contain a huge amount of data.
The structure of these two arrays goes something like this.
arr1 = [
{x: 1, y: '2018-01-01'},
{x: 2, y: '2018-01-02'},
{x: 3, y: '2018-01-03'},
{x: 5, y: '2018-01-05'},
....
]
arr2 = [
{x: 1, y: '2018-01-01'},
{x: 2, y: '2018-01-02'},
{x: 3, y: '2018-01-03'},
{x: 4, y: '2018-01-04'},
{x: 5, y: '2018-01-05'},
{x: 6, y: '2018-01-08'}
]
I want to update arr2 in such a way that it updates the array of objects with values that are only present in arr1 and drop any values not present in arr1. Note, I want to update the original arr2 and not return a new array.
I tried iterating through individual arrays and remove values not present but not luck.
You could get a map and iterate from the end for splicing unknown items or update changed values.
var arr1 = [{ x: 1, y: '2018-01-01x' }, { x: 2, y: '2018-01-02' }, { x: 3, y: '2018-01-03' }, { x: 5, y: '2018-01-05' }],
arr2 = [{ x: 1, y: '2018-01-01' }, { x: 2, y: '2018-01-02' }, { x: 3, y: '2018-01-03' }, { x: 4, y: '2018-01-04' }, { x: 5, y: '2018-01-05' }, { x: 6, y: '2018-01-08' }],
map = arr1.reduce((m, { x, y }) => m.set(x, y), new Map),
i = arr2.length;
while (i--) {
if (map.has(arr2[i].x)) {
if (map.get(arr2[i].x) !== arr2[i].y) {
arr2[i].y = map.get(arr2[i].x);
}
} else {
arr2.splice(i, 1);
}
}
console.log(arr2);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Is it possible to search a object in an array with both of its properties

I have the following code
const xPosition = coordinates.find(position => position.x === avoidObstacleX);
This returns me the coordinates {x: 26, y: 10} this is not wrong, but I have another coordinate that is the one I will like to output which is {x: 26, y: 11} Is there a way I can pass two parameters to the find method?
You could use two variables (not parameters to the find method itself), like you already use one:
function findObstacle(coordinates, avoidObstacleX, avoidObstacleY) {
return coordinates.find(position => position.x === avoidObstacleX
&& position.y === avoidObstacleY);
}
const xyPosition = findObstacle(coordinates, avoidObstacleX, avoidObstacleY);
But from the other answer I now learn that there are two interpretations of your question...
find only retrieves a single element, you need to use the filter method:
const coordinates = [ {x: 26, y: 10}, {x: 26, y: 11}, {x: 12, y: 34} ]
const avoidObstacleX = 26;
// returns [ {x: 26, y: 10}, {x: 26, y: 11} ]
const xPosition = coordinates.filter(position => position.x === avoidObstacleX);
To pass one value:
const coordinates= [
{x: 26, y: 10},
{x: 26, y: 11},
{x: 36, y: 6},
{x: 7,y: 8}
]
const avoidObstacleX=26;
let result = coordinates.filter(position=> {
return position.x === avoidObstacleX ;
})
console.log(result)
You can pass two values:
const coordinates= [
{x: 26, y: 11},
{x: 26, y: 11},
{x: 26, y: 11},
{x: 7,y: 8}
]
function find(avoidObstaclex,avoidObstacley){
let result= coordinates.filter(position=> {
return position.x === avoidObstaclex && position.y === avoidObstacley ;
})
return result;}
const avoidObstacleX=26;
const avoidObstacleY=11;
console.log(find(avoidObstacleX,avoidObstacleY))

How to reverse all arrays inside an object

var data = {
id: 1,
track: {
"1": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
],
"2": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
]
}
}
console.log(data.track);
var rev = data.track["1"].reverse();
console.log(rev);
How can i reverse every array inside "track" object? But I showed you above, that i am able to reverse array, by selecting it by key, but can i literally reverse every array inside "track" object?
Use Object.keys() to find all keys in your data structure
var data = {
id: 1,
track: {
"1": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
],
"2": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
]
}
}
var keys = Object.keys(data.track);
var count = keys.length;
for (var i=0;i<count;i++)
{
var rev = data.track[keys[i]].reverse();
console.log(rev);
}
It's simple. Just loop the data.track to get reverse result.
for (var i in data.track) {
console.log(data.track[i].reverse());
}

Categories

Resources