Merge specific array values into single value - javascript

I have parsed a csv file which gives me an array like this:
[{
"year": 2019,
"month": 6,
"day": 25,
"hour": 4,
"minute": 0,
"temperature": 26.52
},
{
"year": 2019,
"month": 6,
"day": 25,
"hour": 4,
"minute": 0,
"temperature": 26.52
}]
I want to merge minute,hour,day,month,year to a single key. Like this:
"time": "2019-07-02 09:57:35"
so i can use this as a datetime object on my API.
The way I am currently getting data is:
const cleanKeys = [
'year',
'month',
'day',
'hour',
'minute',
'temperature',
];
const dataAsObject = totalData.map(function (values) {
return cleanKeys.reduce(function (o, k, i) {
o[k] = values[i];
return o;
}, {})
});
This is basically adding a header key to all data. I am only interested in merging minute, hour, day, month, year column.

I suggest you to use built in Date constructor:
var obj = {"year": 2019,
"month": 6,
"day": 25,
"hour": 4,
"minute": 0,
"temperature": 26.52};
const date = new Date(obj.year, obj.month - 1, obj.day, obj.hour, obj.minute);
const newObj = {date, temperature: obj.temperature};
console.log(JSON.stringify(newObj));
EDIT:
please find below updated answer using date in loop:
const arr = [{
"year": 2019,
"month": 6,
"day": 25,
"hour": 4,
"minute": 0,
"temperature": 26.52
},
{
"year": 2019,
"month": 6,
"day": 25,
"hour": 4,
"minute": 0,
"temperature": 26.52
}];
const newArr = arr.reduce((a,c) => {
const date = new Date(c.year, c.month - 1, c.day, c.hour, c.minute);
a.push({date, temperature: c.temperature});
return a;
}, []);
console.log(JSON.stringify(newArr));

You can create the string yourself, e.g.:
yourArray["time"] = `${yourArray.year}-${yourArray.month}-${yourArray.day} ${yourArray.hours}:${yourArray.minutes}:${yourArray.seconds}`;

Related

Compare common columns from two list and create a new list according with the match and mismatch

this.monthList.map(sli_record => {
let rec_found = this.newlist.find(vale_record =>vale_record.Value === sli_record.Value);
if(rec_found) {
this.Results['Value'] = sli_record['Value'];
this.Results['Month'] = sli_record['Month'];
this.Results['Year'] = sli_record['Year'];
this.Results['IsSubmittedID'] = sli_record['IsSubmittedID'];
this.Results['IsEligible'] = sli_record['IsEligible'];
this.Results['BackgroundCheckdone'] = sli_record['BackgroundCheckdone'];
}
else {
this.Results['Value'] = sli_record['Value'];
this.Results['Month'] = sli_record['Month'];
this.Results['Year'] = sli_record['Year'];
this.Results['IsSubmittedID'] = 0;
this.Results['IsEligible'] = 0;
this.Results['BackgroundCheckdone'] = 0;
this.Results['UserPass'] = sli_record['UserPass'];
}
//console.log(this.Results);
return this.Results;
}
Hi I am trying to check a common value tag of one list against another and fill in the data to a new list new list "Results" according to the conditional check but not able to generate the desired result.
Whenever the column "Value" from newlist is compared with the "Value" of monthList, if there is no value exist for that particular entry(Value column of newlist) in the monthList then it should create a entry with default values in the newlist array
for eg: Consider this value
{Id: 3, Value: 'June 2022'}
this does not exist on the newlist as of now but it should add an new entry like below to the newlist array
{
"Value": "June 2022",
"Month": "June",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 0,
"BackgroundCheckdone": 0
}
newlist=[
{ Id: 0,
Month: 'May',
Year: 2022,
Value: 'February 2022',
IsSubmittedID: 0,
IsEligible: 1,
BackgroundCheckdone: 1,
},
{Id: 0,
Month: 'July',
Year: 2022,
Value: 'July 2022',
IsSubmittedID: 0,
IsEligible: 1,
BackgroundCheckdone: 1,
}]
monthList =[
{Id: 1, Value: 'August 2022'}
{Id: 2, Value: 'July 2022'}
{Id: 3, Value: 'June 2022'}
{Id: 4, Value: 'May 2022'}
{Id: 5, Value: 'April 2022'}]
**I should get my result as of below for the Results list not able to figure out how to bind the value for the according to the list**
[
{
"Value": "August 2022",
"Month": "August",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 0,
"BackgroundCheckdone": 0
},
{
"Value": "July 2022",
"Month": "July",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 1,
"BackgroundCheckdone": 1
},
{
"Value": "June 2022",
"Month": "June",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 0,
"BackgroundCheckdone": 0
},
{
"Value": "May 2022",
"Month": "May",
"Year": 2022,
"IsSubmittedID": 1,
"IsEligible": 1,
"BackgroundCheckdone": 1
}
]

How to merge two objects with same property in Node JS

I have a JSON Data like this:
"Data": [
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
]
I want to merge two objects in this array, but it have same properties like date, dow
at the end I want to represent data like this:
"Data": [
{
"time": "16:39:52",
"count": 18,
"date": "2019-01-16",
"dow": "Thursday"
"endTime": "19:41:03",
},
]
time: should be least from both objects and endTime should be largest of both of them
count should be sum of both. date and dow is common in both objects
How can I merge these object in this way in node JS?
const data=[
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
];
let date=(time)=>new Date().setHours(...time.split(":"));
let newData=[];
data.forEach((item)=>{
let findItem=newData.findIndex((e)=>e.date===item.date && e.dow===item.dow);
if(findItem!=-1){
let find=data.filter((e)=>e.dow===item.dow && e.date===item.date);
let time=find.filter((i)=>find.find(i2=>date(i2.time)>date(i.time)));
let endTime=find.filter((i)=>find.find(i2=>date(i2.endTime)<date(i.endTime)));
item.endTime=endTime?.[0]?.endTime || item?.endTime;
item.time=time?.[0]?.time || item?.time;
item.count=find.map((e)=>e.count).reduce((partialSum, a) => partialSum + a, 0);
let findItem=newData.findIndex((e)=>e.date===item.date && e.dow===item.dow);
if(findItem!=-1) newData.splice(findItem,1);
newData.push(item);
}
else newData.push(item);
});
console.log(newData);
Here's a simple and readable answer:
const data = [
{
time: "18:40:43",
count: 7,
endTime: "15:46:25",
date: "2019-01-16",
dow: "Thursday",
},
{
count: 11,
time: "16:39:52",
endTime: "19:41:03",
dow: "Thursday",
date: "2019-01-16",
},
];
const mergeObjects = (data) => {
mergedObj = { ...data[0] };
for (i = 1; i < data.length; i++) {
const obj = data[i];
for (const key in obj) {
switch (key) {
case "count":
mergedObj.count = (mergedObj.count || 0) + obj.count;
case "time":
mergedObj.time =
mergedObj.time < obj.time ? mergeObjects.time : obj.time;
case "endTime":
mergedObj.endTime = mergedObj.endTime > obj.endTime ? mergeObjects.endTime : obj.endTime;
}
}
}
return mergedObj;
};
console.log(mergeObjects(data));
output
{
"time": "16:39:52",
"count": 18,
"date": "2019-01-16",
"dow": "Thursday"
"endTime": "19:41:03",
},
Assuming
"Data" would have only two objects inside it
time would be in "HH::MM::SS" format
Pass the values onto constructJSON utility function which would return the formatted value
var Data = [
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
]
function constructJSON(data)
{
const returnData = {}
returnData['count'] = data[0].count + data[1].count
returnData['date'] = data[0].date // since its common for both
returnData['dow'] = data[0].dow // since its common for both
returnData['time'] = parseInt(data[0].time.split(':').join(''),10) < parseInt(data[1].time.split(':').join(''),10) ? data[0].time:data[1].time;
returnData['endTime'] = parseInt(data[0].endTime.split(':').join(''),10) > parseInt(data[1].endTime.split(':').join(''),10) ? data[0].endTime:data[1].endTime;
return returnData
}
console.log(constructJSON(Data))
If you use Array.reduce, you should be able to do this pretty easily, it should also expand to let you expand with more than just 2 objects in the array.
const data = [{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
];
//res will contain the output
const res = data.reduce(function(acc, curr) {
//Initially the accumulator will be null
if (!acc) return curr;
//Add the counts up
acc.count += curr.count;
//Convert both times into dates and find the minimum
const accTime = new Date(acc.date + 'T' + acc.time); //We add the T here since that's just how the Date constructor accepts times
const currTime = new Date(acc.date + 'T' + curr.time);
acc.time = new Date(Math.min(accTime, currTime)).toTimeString().split(' ')[0]; //See https://stackoverflow.com/questions/19346405/how-to-get-hhmmss-from-date-object
//Do the same for the end times but find the maximum
const accEndTime = new Date(acc.date + 'T' + acc.endTime);
const currEndTime = new Date(acc.date + 'T' + curr.endTime);
acc.endTime = new Date(Math.max(accEndTime, currEndTime)).toTimeString().split(' ')[0];
return acc;
});
console.log(res);
Another way of merging - all keys are combined, the common keys are overwritten by the second object, but count, time and endTime are calculated by special conditions
const
data = [{"time": "18:40:43","count": 7,"endTime": "15:46:25","date": "2019-01-16","dow": "Thursday"},{"count": 11,"time": "16:39:52","endTime": "19:41:03","dow": "Thursday","date": "2019-01-16"}],
[first, last] = data,
dumbDate = '2000-01-01 ',
result = {
...first,
...last,
count: first.count + last.count,
time: (new Date(`${dumbDate}${first.time}`) < new Date(`${dumbDate}${last.time}`)) ? first.time : last.time,
endTime: (new Date(`${dumbDate}${first.endTime}`) > new Date(`${dumbDate}${last.endTime}`)) ? first.endTime : last.endTime,
};
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}
Use Array#reduce() and Array#map() methods as follows:
const data = {"Data": [{"time": "18:40:43", "count": 7, "endTime": "15:46:25", "date": "2019-01-16", "dow": "Thursday"}, {"count": 11, "time": "16:39:52", "endTime": "19:41:03", "dow": "Thursday", "date": "2019-01-16" }]};
const newD = {Data:data.Data.reduce(
(prev,{date,dow,count,...r}) =>
//check if an element in array prev has dow & date props equal to the current element
prev.findIndex(p => p.date === date && p.dow === dow) > -1 ?
//If found process the matching element
prev.map(({date:d,dow:w,count:c,...rs}) =>
d === date && w === dow ?
({...rs,date:d,dow:w,count:c+count,time:rs.time < r.time ? rs.time : r.time,endTime:rs.endTime > r.endTime ? rs.endTime : r.endTime}) :
({...rs,date:d,dow:w,count:c})
) :
//If not add the current element to array prev
prev.concat({...r,date,dow,count}),
//start off with an empty array
[]
)};
console.log( newD );

Getting dates from JSON for D3

My JSON file has the dates separated like this:
"time": {
"date": {
"year": 2018,
"month": 2,
"day": 25
},
"time": {
"hour": 10,
"minute": 19,
"second": 6,
"nano": 19000000
}
},
The tutorial I used to get a line graph in d3 going was in this link:
https://datawanderings.com/2019/10/28/tutorial-making-a-line-chart-in-d3-js-v-5/
Using the code below:-
const timeConv = d3.timeParse("%d-%b-%Y");
const dataset = d3.csv(datacsv);
dataset.then(function(data) {
var slices = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d){
return {
date: timeConv(d.date),
measurement: +d[id]
};
})
};
});
});
How could I use the same code but use the JSON file with the separated date values?
Just make up the actual date string from the separate dates:
return {
date: timeConv(d.time.date.day + '-' + d.time.date.month + '-' + d.time.date.year),
measurement: +d[id]
};
Since the month is not described as the abbreviated month name, you need to change timeConv as
const timeConv = d3.timeParse("%d-%m-%Y");
An json data example:
let dataset = [{
"id": 1,
"time": {
"date": {
"year": 2018,
"month": 2,
"day": 25
},
"time": {
"hour": 10,
"minute": 19,
"second": 6,
"nano": 19000000
}
}
}, {
"id": 2,
"time": {
"date": {
"year": 2019,
"month": 2,
"day": 25
},
"time": {
"hour": 10,
"minute": 19,
"second": 6,
"nano": 19000000
}
}
}]
const timeConv = d3.timeParse("%d-%m-%Y");
newData = dataset.map(function(d) {
return {
date: timeConv(d.time.date.day + '-' + d.time.date.month + '-' + d.time.date.year),
measurement: +d.id
}
})
console.log(newData)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Push data to array without using if statement

I have following output. it gives my API.
{
"_id": {
"year": 2018,
"month": 6,
"day": 11,
"hour": 12,
"interval": 45,
"method": "200"
},
"count": 1
},
{
"_id": {
"year": 2016,
"month": 11,
"day": 11,
"hour": 16,
"interval": 50,
"method": "404"
},
"count": 5
},
{
"_id": {
"year": 2016,
"month": 11,
"day": 11,
"hour": 17,
"interval": 10,
"method": "200"
},
"count": 47
}}
I want to Push them to arrays according to method. As an example
twoHundArray=[
{ "x":2018,6,11,12,45,
"y" :1},
{"x": 2016,11,11,17,10 ,
"y" :47}]
fourhundrArry=[{ "x":2018,11,11,16,50,
"y" :5}]
without using if/else statement how to push them to different arrays. In here I don't know all the names of methods.so cannot use if statement for "method".that is the problem here.
The original object is invalid. You can't have elements in an object without specifying the keys. I've assumed that it is an array.
Secondly, there is no way of pushing elements to different arrays without knowing their names. So the judgement of pushing the elements to different variables will have to be based on if/else conditions. Additionally, creation of those variables will vary based on the groups, as method could have been any value.
If you agree to group the objects based on the values method have, here is a way to do this:
const data = [{"_id":{"year":2018,"month":6,"day":11,"hour":12,"interval":45,"method":"200"},"count":1},{"_id":{"year":2016,"month":11,"day":11,"hour":16,"interval":50,"method":"404"},"count":5},{"_id":{"year":2016,"month":11,"day":11,"hour":17,"interval":10,"method":"200"},"count":47}];
const res = {};
data.forEach(item => {
const { method, ...obj } = item['_id'];
res[method] = res[method] || [];
res[method].push({
x: Object.values(obj),
y: item.count
});
});
console.log(res);
It creates an object, whose keys are method. The values in the object are the arrays, which contain the items grouped by method.
You can use Array.reduce and create a map based on method. Try the following:
var data = [{
"_id": {
"year": 2018,
"month": 6,
"day": 11,
"hour": 12,
"interval": 45,
"method": "200"
},
"count": 1
},
{
"_id": {
"year": 2016,
"month": 11,
"day": 11,
"hour": 16,
"interval": 50,
"method": "404"
},
"count": 5
},
{
"_id": {
"year": 2016,
"month": 11,
"day": 11,
"hour": 17,
"interval": 10,
"method": "200"
},
"count": 47
}];
var method = data.reduce((a,o)=>{
if(!a[o._id.method]){
a[o._id.method] = [];
};
var { method, ...ob } = o._id;
a[o._id.method].push({
"x": Object.values(ob).join(","),
"y" : o.count
});
return a;
}, {});
console.log(method);
You can create an object with status:values key/pair using Array.reduce and post that using Object destructuring and default assignment, create independent variables.
const arr = [{"_id":{"year":2018,"month":6,"day":11,"hour":12,"interval":45,"method":"200"},"count":1},{"_id":{"year":2016,"month":11,"day":11,"hour":16,"interval":50,"method":"404"},"count":5},{"_id":{"year":2016,"month":11,"day":11,"hour":17,"interval":10,"method":"200"},"count":47}];
let obj = arr.reduce((a,c) => {
a[c._id.method] = a[c._id.method] || [];
a[c._id.method].push({"x" : Object.values(c._id).join(), "y" : c.count});
return a;
},{});
/* You can add an entry here for every status type, it will pick the
** value from object and if not present will be defaulted to an empty array */
const {200 : twoHundArray=[], 404 : fourHundArray=[], 300 : threeHundArray=[]} = obj;
console.log(twoHundArray);
console.log(fourHundArray);
console.log(threeHundArray);
#Palani, I'll suggest you to use an object to gather all the required information.
Please have a look at the below code and let me know any suggestions/modifications if you need.
var timeDataArr = [
{
"_id": {
"year": 2018,
"month": 6,
"day": 11,
"hour": 12,
"interval": 45,
"method": "200"
},
"count": 1
},
{
"_id": {
"year": 2016,
"month": 11,
"day": 11,
"hour": 16,
"interval": 50,
"method": "404"
},
"count": 5
},
{
"_id": {
"year": 2016,
"month": 11,
"day": 11,
"hour": 17,
"interval": 10,
"method": "200"
},
"count": 47
}
]
// An object that maps 'method' to its related data array
var newTimeData = {}
for(var timeData of timeDataArr) {
var obj = timeData["_id"];
var arr = [obj["year"], obj["month"], obj["day"], obj["hour"], obj["interval"]];
var newObj = {
"x": arr.join(", "),
"y": timeData["count"],
}
if(newTimeData[obj["method"] + "Array"]) { // method found
newTimeData[obj["method"] + "Array"].push(newObj)
} else { // method not found
newTimeData[obj["method"] + "Array"] = [newObj]
}
}
// PRETTY PRINTING OBJECT
console.log(JSON.stringify(newTimeData, undefined, 4))
/*...
{
"200Array": [
{
"x": "2018, 6, 11, 12, 45",
"y": 1
},
{
"x": "2016, 11, 11, 17, 10",
"y": 47
}
],
"404Array": [
{
"x": "2016, 11, 11, 16, 50",
"y": 5
}
]
}
...*/
// PRETTY PRINTING ARRAY POINTED BY '200Array' key
console.log(JSON.stringify(newTimeData["200Array"], undefined, 4))
/*...
[
{
"x": "2018, 6, 11, 12, 45",
"y": 1
},
{
"x": "2016, 11, 11, 17, 10",
"y": 47
}
]
...*/
// PRETTY PRINTING ARRAY POINTED BY '404Array' key
console.log(JSON.stringify(newTimeData["404Array"], undefined, 4))
/*...
[
{
"x": "2016, 11, 11, 16, 50",
"y": 5
}
]
...*/
Output ยป
H:\RishikeshAgrawani\Projects\Sof\FilterArrays>node FilterArrays.js
{
"200Array": [
{
"x": "2018, 6, 11, 12, 45",
"y": 1
},
{
"x": "2016, 11, 11, 17, 10",
"y": 47
}
],
"404Array": [
{
"x": "2016, 11, 11, 16, 50",
"y": 5
}
]
}
[
{
"x": "2018, 6, 11, 12, 45",
"y": 1
},
{
"x": "2016, 11, 11, 17, 10",
"y": 47
}
]
[
{
"x": "2016, 11, 11, 16, 50",
"y": 5
}
]

Get specific values of nested object within array

I make an AJAX request and I receive this (looking at the Network tab)
[
{
"request": "Amount of rainfall by day",
"days": [
{
"day": 1,
"amount": 50
}, {
"day": 2,
"amount": 10
}, {
"day": 3,
"amount": 10
}, {
"day": 4,
"amount": 150
}, {
"day": 5,
"amount": 130
}, {
"day": 6,
"amount": 45
}, {
"day": 7,
"amount": 10
}
]
}
]
I would like to create an array with the values of 'amount'.
[50,10,10,150,130,45,10]
(the order is important; I will show these values in a chart with chronological order)
I tried lodash.values as well as for..in but the mix between nested arrays and nested objects is rather confusing.
I would like an elegant solution.
Question 1: Should I use a Json method to remove the outside root level array ? Any way to get rid of it?
Question 2: Which data structure should I use in order to keep the relation between days and amounts? (my charting library, Chart.js receives a simple array of single values.
Use Array#map to create a new array from the requested values:
var data = [{"request":"Amount of rainfall by day","days":[{"day":1,"amount":50},{"day":2,"amount":10},{"day":3,"amount":10},{"day":4,"amount":150},{"day":5,"amount":130},{"day":6,"amount":45},{"day":7,"amount":10}]}];
var result = data[0].days.map(function(obj) {
return obj.amount;
});
console.log(result);
Question 1
You can tranverse it easily by using data[0], and after you'll map / reduce, you'll get a new data structure.
Question 2
You can use a simple object, with two related arrays by using Array#reduce:
var data = [{"request":"Amount of rainfall by day","days":[{"day":1,"amount":50},{"day":2,"amount":10},{"day":3,"amount":10},{"day":4,"amount":150},{"day":5,"amount":130},{"day":6,"amount":45},{"day":7,"amount":10}]}];
var result = data[0].days.reduce(function(r, o) {
r.days.push(o.day);
r.amounts.push(o.amount);
return r;
}, { days: [], amounts: [] });
console.log(JSON.stringify(result));
I use the Lodash to answer your question
var response = [
{
"request": "Amount of rainfall by day",
"days": [
{
"day": 1,
"amount": 50
}, {
"day": 2,
"amount": 10
}, {
"day": 3,
"amount": 10
}, {
"day": 4,
"amount": 150
}, {
"day": 5,
"amount": 130
}, {
"day": 6,
"amount": 45
}, {
"day": 7,
"amount": 10
}
]
}
];
// using _.map function
_.map(response[0].days, 'amount');
Lodash
Use this:
var reply = [
{
"request": "Amount of rainfall by day",
"days": [
{
"day": 1,
"amount": 50
}, {
"day": 2,
"amount": 10
}, {
"day": 3,
"amount": 10
}, {
"day": 4,
"amount": 150
}, {
"day": 5,
"amount": 130
}, {
"day": 6,
"amount": 45
}, {
"day": 7,
"amount": 10
}
]
}
];
var amounts = reply[0].days.map((i) => { return i.amount });
console.log(amounts);
In case the day property value does not follow the order of the elements in the response object, you may need to use that value as index in your final array. Here is an ES6 solution:
var response = [
{
"request": "Amount of rainfall by day",
"days": [
{
"day": 1,
"amount": 50
}, {
"day": 2,
"amount": 10
}, {
"day": 3,
"amount": 10
}, {
"day": 4,
"amount": 150
}, {
"day": 5,
"amount": 130
}, {
"day": 6,
"amount": 45
}, {
"day": 7,
"amount": 10
}
]
}
];
var arr = response[0].days.reduce( (arr, o) => (arr[o.day-1] = o.amount, arr), []);
console.log(arr);
So this would even work if the value for day 4 were missing. The value at the corresponding index in the output array (index 3) would have undefined in that case.

Categories

Resources