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 );
Related
I have an array which is like this:
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
I want to match the primary key which is heredate. Matching this I want to merge the rest of the key values and get this following output:
[{
"date": "JAN",
"value": [5, 4],
"weight": [3, 23]
}, {
"date": "FEB",
"value": [9, 10],
"weight": [1, 30]
}]
I have written a function like this but can't figure out how to concat the key values:
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
const transform = (arr, primaryKey) => {
var newValue = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 1; j < arr.length; j++) {
if (primaryKey[i] === primaryKey[j]) {
newValue.push({
...arr[i],
...arr[j]
});
}
}
}
return newValue
};
console.log(transform(arr,'date'))
Using Array#reduce, iterate over the list while updating a Map where the key is the primary-key and the value is the grouped object. In every iteration, create/update the pair.
Using Map#values, return the list of grouped objects
const transform = (arr, primaryKey) => [...
arr.reduce((map, { [primaryKey]: key, ...e }) => {
const { [primaryKey]: k, ...props } = map.get(key) ?? {};
for(let prop in e) {
props[prop] = [...(props[prop] ?? []), e[prop]];
}
map.set(key, { [primaryKey]: key, ...props });
return map;
}, new Map)
.values()
];
const arr = [ { "date": "JAN", "value": 5, "weight": 3 }, { "date": "JAN", "value": 4, "weight": 23 }, { "date": "FEB", "value": 9, "weight": 1 }, { "date": "FEB", "value": 10, "weight": 30 } ];
console.log( transform(arr, 'date') );
The following code should work:
const transform = (arr, primaryKey) => {
var newValue = [];
for(let i = 0; i < arr.length; i++){
arr[i]["value"] = [arr[i]["value"]];
arr[i]["weight"] = [arr[i]["weight"]];
}
newValue.push(arr[0])
for(let i = 1; i < arr.length; i++){
let contains = false;
for(let j = 0; j < newValue.length; j++){
if(newValue[j][primaryKey] == arr[i][primaryKey]){
newValue[j]["value"].push(arr[i]["value"][0]);
newValue[j]["weight"].push(arr[i]["weight"][0]);
contains = true;
}
}
if(!contains){
newValue.push(arr[i]);
}
}
return newValue
};
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
var newthing = transform(arr,"date");
console.log(newthing);
Output:
[ { date: 'JAN', value: [ 5, 4 ], weight: [ 3, 23 ] },
{ date: 'FEB', value: [ 9, 10 ], weight: [ 1, 30 ] } ]
The way this code works is that first, we turn the values of the keys for "value" and "weight" into lists.
Then, we begin by pushing the first element of arr into newValue.
From here, we do a nested for loop to iterate through the remaining of arr and newValue:
If the value of "date" for every element of arr already exists in newValue, then we will push in the values of "value" and "weight" that belongs to arr.
However, if it does not exist, then we will simply push that element inside of newValue.
I hope this helped answer your question! Pleas let me know if you need any further help or clarification :)
Combining a couple of reduce can also do the same job:
const arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
const arrayMappedByDate = arr.reduce((acc, curData) => {
if (acc[curData.date]) {
acc[curData.date].push(curData)
} else {
acc[curData.date] = [curData]
}
return acc
}, {})
const transformedArray = Object.entries(arrayMappedByDate).map(([dateInit, data]) => {
const normalized = data.reduce((acc, cur) => {
if (acc.date) {
acc.value.push(cur.value)
acc.weight.push(cur.weight)
} else {
acc = {
date: cur.date,
value: [cur.value],
weight: [cur.weight]
}
}
return acc
}, {})
return { [dateInit]: normalized }
})
console.log(transformedArray)
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>
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}`;
I have two array of objects that looks this in JSON format:
{
"Arr1":
[
{ "_id": "firstSub1", "count": 1, "price": 4 },
{ "_id": "firstSub2", "count": 2, "price": 7 },
{ "_id": "firstSub3", "count": 3, "price": 1 }
{ "_id": "firstSub4", "count": 4, "price": 1 }
],
"Arr2":
[
{ "name": "firstSub1", "date": 05 / 20 / 1998, "type": sometype1 },
{ "name": "firstSub2" "date": 12 / 22 / 2011, "type": sometype2 },
{ "name": "firstSub3", "date": 09 / 23 / 2004, "type": sometype3 }
{ "name": "firstSub9", "date": 09 / 23 / 2004, "type": sometype9 }
]
//Desired Output
"finalArray":
[
{ "name": "firstSub1", "date": 05 / 20 / 1998, "type": sometype1, "count": 1, "price": 4 },
{ "name": "firstSub2" "date": 12 / 22 / 2011, "type": sometype2, "count": 2, "price": 7 },
{ "name": "firstSub3", "date": 09 / 23 / 2004, "type": sometype3, "count": 3, "price": 1 },
{ "name": "firstSub9", "date": 09 / 23 / 2004, "type": sometype9 },
{ "_id": "firstSub4", "count": 4, "price": 1 }
]
}
I need to compare _id in the first array and see if there is a match with name in the Arr2 and match them if _id === name.
I have tried using lodash and its undescores, and mapping functions like this:
mergeArray() {
.... //pulling data
let Arr1 = data['Arr1Data'];
let Arr2 = data['Arr2Data'];
let finalArray = Arr2.map((e, _) =>
(_ = Arr1.find((q) => e.name === q._id)) ?
{ ...e, ..._ } : e)
console.log(finalArray)
}
All of the data from Arr2 is coming back and merging with only half of the data Arr1 my data is not coming back with the desired output...how can i map these two arrays and have a union and intersection?
Using vanilla Js, you can get an array of unique _id and name from both arrays, loop throught it and join the object from both arrays that matches the current id in the iteration :
Deduped array of ids and names :
const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];
Loop to join elements from both arrays :
const result = ids.map(e => ({
...Arr1.find(o => o._id === e),
...Arr2.find(o => o.name === e)
}))
const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3, "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}];
const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}];
const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];
const result = ids.map(e => ({
...Arr2.find(o => o.name === e),
...Arr1.find(o => o._id === e)
}))
console.log(result)
EDIT :
You can tweak the returned object in .map() to remove properties ( like _id) :
const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3, "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}];
const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}];
const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];
const result = ids.map(e => {
const obj = {
...Arr2.find(o => o.name === e),
...Arr1.find(o => o._id === e)
}
if(obj.name && obj._id) delete obj._id;
return obj;
})
console.log(result)
You can use lodash's _.flow() to create a function that combines the arrays, groups them by name or _id (whatever is found on the object). If the a group contains more than 1 item, it's merged to a single object, and the _id property is omitted.
const { flow, partialRight: pr, concat, groupBy, map, merge, has, head, omit } = _
const fn = flow(
concat, // combine to a single array
pr(groupBy, o => o.name || o._id), // group by the value of name or _id
pr(map, o => o.length === 1 ? head(o) : _.omit( // if a group contains 2 items merge them, and remove _id
merge({}, ...o),
'_id'
)),
)
const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3, "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}]
const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}]
const result = fn(Arr2, Arr1)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
One solution is to use Array.reduce() starting with an accumulator equal to a copy of Arr2 (JSON.parse(JSON.stringify(Arr2))) so we don't mutate the original array Arr2. Now, while iterating over Arr1, if we found a match then we add the related properties using Object.assign() to the associated object on the accumulator, otherwise we put the entire object on the accumulator:
const Arr1 = [
{"_id": "firstSub1", "count": 1, "price": 4},
{"_id": "firstSub2", "count": 2, "price": 7},
{"_id": "firstSub3", "count": 3, "price": 1},
{"_id": "firstSub4", "count": 4, "price": 1}
];
const Arr2 = [
{"name": "firstSub1", "date": "05/20/1998", "type": "sometype1"},
{"name": "firstSub2", "date": "12/22/2011", "type": "sometype2"},
{"name": "firstSub3", "date": "09/23/2004", "type": "sometype3"},
{"name": "firstSub9", "date": "09/23/2004", "type": "sometype9"}
];
let res = Arr1.reduce((acc, {_id, count, price}) =>
{
let fIdx = acc.findIndex(({name}) => name === _id);
if (fIdx >= 0)
Object.assign(acc[fIdx], {count, price});
else
acc.push({_id, count, price});
return acc;
}, JSON.parse(JSON.stringify(Arr2)));
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
You can sort by name and compare the i + 1 index name to validate if the i + 1 index and the i index should be merged or if the object doesn't have a pair for merging.
For example, sorting by name means that the next object/index will be the pair.
[{name: "firstSub1", count: 1}, {name: "firstSub1", date: "dd / mm / yyyy"}] // Pair found
or
[{name: "firstSub1", count: 1}, {name: "firstSub2", count: 1}] // There is no a pair
This is assuming there is max one pair
let obj = { "Arr1": [{ "_id": "firstSub1", "count": 1, "price": 4 }, { "_id": "firstSub2", "count": 2, "price": 7 }, { "_id": "firstSub3", "count": 3, "price": 1 }, { "_id": "firstSub4", "count": 4, "price": 1 } ], "Arr2": [{ "name": "firstSub1", "date": "05 / 20 / 1998", "type": "sometype1" }, { "name": "firstSub2", "date": "12 / 22 / 2011", "type": "sometype2" }, { "name": "firstSub3", "date": "09 / 23 / 2004", "type": "sometype3" }, { "name": "firstSub9", "date": "09 / 23 / 2004", "type": "sometype9" } ]};
// All objects in one array.
let merge = [...obj.Arr2,
// The map is to change _id by name, this is used later.
...obj.Arr1.map(({_id, count, price}) => ({name: _id, count, price}))]
.sort((a, b) => a.name.localeCompare(b.name));
// This approach doesn't mutate the source objects.
let result = [];
for (let i = 0; i < merge.length;) {
if (merge[i + 1] && merge[i + 1].name === merge[i].name) {
result.push(Object.assign(Object.create(null), merge[i], merge[i + 1]));
i++;
} else result.push(merge[i]);
i++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have an JSON like this
"result": [{
"channel": "A",
"mkp": "ABC",
"qtd": 6,
"total": 2938.2,
"data": "2019-02-16",
"time": "22:30:40"
}, {
"channel": "C",
"mkp": "DEF",
"qtd": 1545,
"total": 2127229.64,
"data": "2019-02-20",
"time": "17:19:49"
}, {
"channel": "C",
"mkp": "JKL",
"qtd": 976,
"total": 1307328.37,
"data": "2019-02-20",
"time": "17:19:53"
}, {
"channel": "U",
"mkp": "PQR",
"qtd": 77,
"total": 98789.87,
"data": "2019-02-20",
"time": "16:12:31"
}, {
"channel": "U",
"mkp": "STU",
"qtd": 427,
"total": 433206.62,
"data": "2019-02-20",
"time": "17:04:27"
}
]
I need to sum the QTD, the total and return the newest data + time when the channel is the same (eg.: Channel C and U have 2 entries), if it's not so I only will display the values, but I can't figure it out how could I iterate and do these math. Someone could help?
A sample of what I want:
"A": [{
"qtd": 6,
"total": 2938.20,
"dateTime": 2019 - 02 - 16 22: 30: 40 "
}],
"C": [{
"qtd": 2.521,
"total": 3434558.01,
"dateTime": 2019 - 02 - 20 17: 19: 53 "
}],
"U": [{
"qtd": 504,
"total": 531996,
49,
"dateTime": 2019 - 02 - 20 17: 04: 27 "
}]
Currently I separated the values using filter like this:
this.channelA = this.receivedJson.filter(({ channel }) => channel === "A");
You could use reduce method and return one object with object as values.
const data = [{"channel":"A","mkp":"ABC","qtd":6,"total":2938.2,"data":"2019-02-16","time":"22:30:40"},{"channel":"C","mkp":"DEF","qtd":1545,"total":2127229.64,"data":"2019-02-20","time":"17:19:49"},{"channel":"C","mkp":"JKL","qtd":976,"total":1307328.37,"data":"2019-02-20","time":"17:19:53"},{"channel":"U","mkp":"PQR","qtd":77,"total":98789.87,"data":"2019-02-20","time":"16:12:31"},{"channel":"U","mkp":"STU","qtd":427,"total":433206.62,"data":"2019-02-20","time":"17:04:27"}]
const res = data.reduce((r, {channel, qtd, total, data, time}) => {
const dateTime = `${data} ${time}`
if(!r[channel]) r[channel] = {qtd, total, dateTime}
else {
r[channel].total += total
r[channel].qtd += qtd;
r[channel].dateTime = dateTime
}
return r;
}, {})
console.log(res)
You an use reduce to group the values based on channel like this:
const input = [{"channel":"A","mkp":"ABC","qtd":6,"total":2938.2,"data":"2019-02-16","time":"22:30:40"},{"channel":"C","mkp":"DEF","qtd":1545,"total":2127229.64,"data":"2019-02-20","time":"17:19:49"},{"channel":"C","mkp":"JKL","qtd":976,"total":1307328.37,"data":"2019-02-20","time":"17:19:53"},{"channel":"U","mkp":"PQR","qtd":77,"total":98789.87,"data":"2019-02-20","time":"16:12:31"},{"channel":"U","mkp":"STU","qtd":427,"total":433206.62,"data":"2019-02-20","time":"17:04:27"}]
const merged = input.reduce((acc, { channel, qtd, total, data, time }) => {
acc[channel] = acc[channel] || [{ qtd: 0, total: 0, dateTime:'' }];
const group = acc[channel][0];
group.qtd += qtd;
group.total += total;
const dateTime = `${data} ${time}`
if(dateTime > group.dateTime)
group.dateTime = dateTime;
return acc;
}, {})
console.log(merged)