Related
I'm trying to filter the array by the numbers. Basically, car with id 48 should be deleted because it does not exist on numbers
What am I missing here??
const numbers = [49, 482, 49, 49, 49, 1135, 49, 1709, 1044, 1016, 30];
const array = [{
cars: [{
id: 48
}, {
id: 49
}]
}];
array.forEach(elem => elem.cars.filter(car => !numbers.includes(car.id)));
console.log(array);
I want to keep the same structure, I just want tot delete the car with id 48
You can use a nested forEach
const numbers = [49, 482, 49, 49, 49, 1135, 49, 1709, 1044, 1016, 30];
const array = [{
cars: [{
id: 48
}, {
id: 49
}]
}];
array.forEach(elm => {
const cars = [];
elm.cars.forEach(car => {
if(numbers.includes(car.id)) {
cars.push({id: car.id});
}
});
elm.cars = cars;
});
console.log(array);
Or a reduce within forEach
const numbers = [49, 482, 49, 49, 49, 1135, 49, 1709, 1044, 1016, 30];
const array = [{
cars: [{
id: 48
}, {
id: 49
}]
}];
array.forEach(elm => {
elm.cars = elm.cars.reduce((acc, curr) => {
if (numbers.includes(curr.id)) {
acc.push({
id: curr.id
});
}
return acc;
}, []);
});
console.log(array);
You could use Array.reduce() to acheive the expected result.
The idea is to change the filter condition which allows to keep the car objects id found in the numbers array and eliminate rest.
In your approach Array.forEach is just iteration without returning anything and Array.filter does not mutate the actual array.
const numbers = [49, 482, 49, 49, 49, 1135, 49, 1709, 1044, 1016, 30];
const array = [
{
cars: [
{
id: 48,
},
{
id: 49,
},
],
},
];
const res = array.reduce((prev, curr) => {
prev.push({ cars: curr.cars.filter((car) => numbers.includes(car.id)) });
return prev;
}, []);
console.info("result::", res);
const numbers = [49, 482, 49, 49, 49, 1135, 49, 1709, 1044, 1016, 30];
const array = [
{
cars: [{id: 48,},{id: 49,}],
},
];
array.forEach((elem) => {
const elemCopy = elem;
elemCopy.cars = elem.cars.filter((car) => numbers.includes(car.id))
});
console.log(array);
Please refer the code, while iterating over array we can mutate the cars array.
From the object below, I wanted to sum up certain properties (fare+tax and com+agency) by their key group (1345, 2353) and updated it in the current array object.
var details = [{ 1345:[
{route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0}],
2353: [
{route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0},
{route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0}
]}
]
expected output: updated details (totalCost and totalFee)
1345:
{ route: 34, fare: 45, .... totalCost: 91, totalFee: 69 }
2353:
{ route: 32, fare: 45, ... totalCost: 188, totalFee: 90 },
{ route: 42, fare: 34, ... totalCost: 188, totalFee: 176 }
totalCost = fare + tax and totalFee = com + agency
I tried to simplified the array objects and convert by using Object.entries(details[0]), then reduce to sum up the target properties.
Object.entries(details[0]).reduce((acc, curr) => (acc = acc + curr["fare"]+curr["tax"]), 0);
However, NaN was returned.
Would appreciate if anyone could show me how I can loop through each key group and sum up the target values and update it (totalCost and totalFee).
One way (of many) would be to use a simple sum function to sum up an arbitrary array of values:
function sum(...nums) {
return nums.reduce((acc, val) => acc + val)
}
Next, sum up the totalCost/totalFee logic for each key group (1345 and 2353), and then apply the sums to each array entry:
for (const [key, vals] of Object.entries(details[0])) {
vals.forEach((val, _, vals) => {
val.totalFee = sum(...vals.map(val => val.com + val.agency))
val.totalCost = sum(...vals.map(val => val.fare + val.tax))
})
}
Here's the whole shebang:
const details = [
{
1345: [
{route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0},
],
2353: [
{route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0},
{route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0},
],
},
]
for (const [key, vals] of Object.entries(details[0])) {
vals.forEach((val, _, vals) => {
val.totalFee = sum(...vals.map(val => val.com + val.agency))
val.totalCost = sum(...vals.map(val => val.fare + val.tax))
})
}
console.log(JSON.stringify(details, null, 2))
function sum(...nums) {
return nums.reduce((acc, val) => acc + val)
}
We can do this using a few Array.reduce() calls, the end result should be as required.
For each key group, we'd use Object.entries() to get the key and value for the group.
const details = [{ 1345:[ {route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0}], 2353: [ {route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0}, {route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0} ]} ]
const result = details.reduce((acc, group) => {
return Object.entries(group).reduce((acc, [key, routes] ) => {
return routes.reduce((acc, { fare, tax, com, agency}) => {
acc[key] = acc[key] || {};
acc[key].totalCost = (acc[key].totalCost || 0) + fare + tax;
acc[key].totalFee = (acc[key].totalFee || 0) + com + agency;
return acc;
}, acc)
}, acc)
}, {})
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
I've updated here to include the original array under each key group, naming it 'routes', this could be changed to anything:
const details = [{ 1345:[ {route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0}], 2353: [ {route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0}, {route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0} ]} ]
const result = details.reduce((acc, group) => {
return Object.entries(group).reduce((acc, [key, routes] ) => {
return routes.reduce((acc, { fare, tax, com, agency}) => {
acc[key] = acc[key] || { routes };
acc[key].totalCost = (acc[key].totalCost || 0) + fare + tax;
acc[key].totalFee = (acc[key].totalFee || 0) + com + agency;
return acc;
}, acc)
}, acc)
}, {})
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
Expanding on the use of Object.values
var details = [{ 1345:[
{route: 34, fare: 45, tax: 46, date: 46, com: 45, agency: 24, totalCost: 0, totalFee: 0}],
2353: [
{route: 32, fare: 45, tax: 45, date: 56, com: 34, agency: 52, totalCost: 0, totalFee: 0},
{route: 42, fare: 34, tax: 64, date: 34, com: 56, agency: 34, totalCost: 0, totalFee: 0}
]}
]
Object.values(details).map(x => {
details = {}
let count = 0;
for (let y of Object.values(x)) {
y = y.reduce(function (a, b) {
for (const key in b) {
if (a[key]) {
a[key] = a[key] + b[key]
} else {
a[key] = b[key];
}
}
return a;
}, {});
y['totalCost'] = y['fare'] + y['tax'];
y['totalFee'] = y['com'] + y['agency'];
let totalObj = {};
totalObj['totalCost:'] = y['totalCost'];
totalObj['totalFee:'] = y['totalFee'];
details[`${Object.keys(x)[count]}`] = totalObj;
count++;
};
});
console.log(details);
I have the following JavaScript object. I need to generate a new array of objects from the given object. What is the approach I should take in JavaScript?
const ObjOfObj = {
'virus': [
{
'2016': 67,
'2017': 59,
'2018': 18,
'2019': 1
}
],
'cure': [
{
'2016': 51,
'2017': 50,
'2018': 16,
'2019': 1
}
]
};
How can I transform or pivot to generate the following array of objects?
const ArrOfObj = [
{'year': '2016', 'virus': 67, 'cure' : 51},
{'year': '2017', 'virus': 59, 'cure' : 50},
{'year': '2018', 'virus': 18, 'cure' : 16},
{'year': '2019', 'virus': 1, 'cure' : 1},
]
you can use a reduce function like this.
const ObjOfObj = {
'virus': [
{
'2016': 67,
'2017': 59,
'2018': 18,
'2019': 1
}
],
'cure': [
{
'2016': 51,
'2017': 50,
'2018': 16,
'2019': 1
}
]
};
const groupBy = (obj) => {
const keys = Object.keys(obj);
const mapping = keys.reduce((acc, k) => {
obj[k].forEach(item => {
Object.keys(item).forEach(yearKey => {
tracked = acc[yearKey];
if (!tracked) {
acc[yearKey] = {
year: yearKey
};
}
acc[yearKey][k] = (acc[yearKey][k] | 0) + item[yearKey];
});
});
return acc;
}, {});
return Object.entries(mapping);
};
console.log(groupBy(ObjOfObj));
var json =
[
{
id: 11,
name:"app1",
family:"apps",
caseID: 123,
order:1
},
{
id: 12,
name:"app1",
family:"apps",
caseID: 123,
order:2
},
{
id: 13,
name:"app1",
family:"apps",
caseID: 123,
order:3
},
{
id: 14,
name:"app2",
family:"tools",
caseID: 129,
order:1
},
{
id: 15,
name:"app2",
family:"tools",
caseID: 129,
order:2
},
{
id: 16,
name:"app3",
family:"utils",
caseID: 120,
order:1
},
{
id: 17,
name:"app3",
family:"utils",
caseID: 120,
order:2
},
id: 18,
name:"app3",
family:"utils",
caseID: 150,
order:null
}
]
Hello, I would like to sort the array above by the highest "order" key and return the filtered array below. The common key is the caseID. Also, If the order key is null return it.
I've searched and tested some functions and loops but cannot seem to get it rite. Any help will be much appreciated. I'd prefer es2015 if possible.
Thank you!
filtered =
[
{
id: 13,
name:"app1",
family:"apps",
caseID: 123,
order:3
},
{
id: 15,
name:"app2",
family:"tools",
caseID: 129,
order:2
},
{
id: 17,
name:"app3",
family:"utils",
caseID: 120,
order:2
},
{
id: 18,
name:"app3",
family:"utils",
caseID: 150,
order:null
}
]
I would start by getting rid of dupes. You can do this with reduce() and assigning to an object keyed to caseID. You can simultaneously avoid any object with a smaller order than one you've already seen. Then you can take the values of that hash which will be the unique objects base on caseID and sort them like you normally would. For example:
var json = [{ "id": 11, "name":"app1", "family":"apps", "caseID": 123, "order":1},{ "id": 12, "name":"app1", "family":"apps", "caseID": 123, "order":2},{ "id": 13, "name":"app1", "family":"apps", "caseID": 123, "order":3},{ "id": 14, "name":"app2", "family":"tools", "caseID": 129, "order":1},{ "id": 15, "name":"app2", "family":"tools", "caseID": 129, "order":2},{ "id": 16, "name":"app3", "family":"utils", "caseID": 120, "order":1},{ "id": 17, "name":"app3", "family":"utils", "caseID": 120, "order":2},{ "id": 18, "name":"app3", "family":"utils", "caseID": 150, "order":null},]
// get just the filtered items based on caseID
// picking out only the largest
let filtered = json.reduce((a,c) => {
if (!a[c.caseID] || a[c.caseID]['order'] < c.order) a[c.caseID] = c
return a
}, {})
// basic sort
let result = Object.values(filtered).sort((a,b) => b.order - a.order)
console.log(result)
You could use a caseID hashtable and override results you find later if order is higher:
const result = [], hash = {};
for(const el in json) {
const exists = hash[el.caseId];
if(exists) {
if(el.order > exists.order)
Object.assign(exists, el);
} else {
result.push(hash[el.caseId] = {...el});
}
}
You can try following
Method
Create an object with unique case ID as key and value being the item with highest order
Sort based on order
// Code goes here
var json = [{"id":11,"name":"app1","family":"apps","caseID":123,"order":1},{"id":12,"name":"app1","family":"apps","caseID":123,"order":2},{"id":13,"name":"app1","family":"apps","caseID":123,"order":3},{"id":14,"name":"app2","family":"tools","caseID":129,"order":1},{"id":15,"name":"app2","family":"tools","caseID":129,"order":2},{"id":16,"name":"app3","family":"utils","caseID":120,"order":1},{"id":17,"name":"app3","family":"utils","caseID":120,"order":2},{"id":18,"name":"app3","family":"utils","caseID":150,"order":null}];
var map = {};
// Create a map of unique case ID's with highest order
json.forEach((item) => {
if(map[item.caseID]) {
if(map[item.caseID].order < item.order) {
map[item.caseID] = item;
}
} else {
map[item.caseID] = item;
}
});
// Sorting the array based on order
var result = Object.values(map).sort((a,b) => b.order-a.order);
console.log(result);
In ES6:
json.sort((a, b) => a.caseID > b.caseID);
let bad_order = json.filter(v => v.order === null);
let good_order = json.filter(v => v.order !== null);
Example
In ES5:
json.sort(function(a, b) { return a.caseID > b.caseID; });
var bad_order = [];
var good_order = [];
for(var i = 0; i < json.length; i++){
if(json[i].order === null)
bad_order.push(json[i]);
else
good_order.push(json[i]);
}
Example
Use reduce method to create an object where the keys will be the caseID.While creating the object check if the value of the order is more or less that the current order value.If the current value is less the than the new value, replace it with new value.
Then use Object.values(object) to create an array of values from the object
var json = [{
"id": 11,
"name": "app1",
"family": "apps",
"caseID": 123,
"order": 1
},
{
"id": 12,
"name": "app1",
"family": "apps",
"caseID": 123,
"order": 2
},
{
"id": 13,
"name": "app1",
"family": "apps",
"caseID": 123,
"order": 3
},
{
"id": 14,
"name": "app2",
"family": "tools",
"caseID": 129,
"order": 1
},
{
"id": 15,
"name": "app2",
"family": "tools",
"caseID": 129,
"order": 2
},
{
"id": 16,
"name": "app3",
"family": "utils",
"caseID": 120,
"order": 1
},
{
"id": 17,
"name": "app3",
"family": "utils",
"caseID": 120,
"order": 2
}, {
"id": 18,
"name": "app3",
"family": "utils",
"caseID": 150,
"order": null
}
]
var m = json.reduce(function(acc, curr, index) {
if (acc[curr['caseID']] === undefined) {
acc[curr['caseID']] = curr;
} else {
if (acc[curr['caseID']].order < curr.order) {
acc[curr['caseID']] = curr;
}
}
return acc;
}, {})
console.log(Object.values(m))
This should help you filter array of objects.
var filteredMap = {};
json.forEach(function (item) {
filteredMap[item.caseID] = item;
});
var filteredArray = [];
for (var key in filteredMap) {
filteredArray.push(filteredMap[key]);
}
console.log(JSON.stringify(filteredArray));
Sort by order and caseID and then filter by caseID,Here is the code:
var json =
[
{
id: 11,
name:"app1",
family:"apps",
caseID: 123,
order:1
},
{
id: 12,
name:"app1",
family:"apps",
caseID: 123,
order:2
},
{
id: 13,
name:"app1",
family:"apps",
caseID: 123,
order:3
},
{
id: 14,
name:"app2",
family:"tools",
caseID: 129,
order:1
},
{
id: 15,
name:"app2",
family:"tools",
caseID: 129,
order:2
},
{
id: 16,
name:"app3",
family:"utils",
caseID: 120,
order:1
},
{
id: 17,
name:"app3",
family:"utils",
caseID: 120,
order:2
}, {
id: 18,
name:"app3",
family:"utils",
caseID: 150,
order:null
}
]
var obj = {}
var arr = json.sort(function(a, b) {
return b.order - a.order
}).sort(function(a, b) {
return a.caseId - b.caseId
}).filter(function(item, index, array){
return obj.hasOwnProperty(item.caseID) ? false : (obj[item.caseID] = true)
})
console.log(arr)
demo: http://jsbin.com/qabehorike/edit?js,console,output
I need help with recursively transform json object into another json object.
My input object looks like this:
var my_obj = {
"id": 22,
"eventTypeId": 37,
"eventTypeName": "CommonOnly",
"parentEvent": {
"id": 21,
"eventTypeId": 35,
"eventTypeName": "FullTest",
"parentEvent": {
"id": 20,
"parentEvent": null,
"eventTypeId": 38,
"eventTypeName": "FullTest"
}
},
"childrenEvents": [
{
"id": 24,
"parentEventId": 22,
"eventTypeId": 36,
"eventTypeName": "BlindedTest",
"childrenEvents": []
},
{
"id": 23,
"parentEventId": 22,
"eventTypeId": 38,
"eventTypeName": "OneCustom",
"childrenEvents": []
}
]
}
The output I want is:
var my_obj = {
"id": 20,
"eventTypeId": 38,
"parentEvent": null,
"eventTypeName": "FullTest",
"childrenEvents": [{
"id": 21,
"eventTypeId": 35,
"eventTypeName": "FullTest",
"childrenEvents": [
{
"id": 22,
"eventTypeId": 37,
"eventTypeName": "CommonOnly",
"childrenEvents": [
{
"id": 24,
"parentEventId": 22,
"eventTypeId": 36,
"eventTypeName": "BlindedTest",
"childrenEvents": []
}, {
"id": 23,
"parentEventId": 22,
"eventTypeId": 38,
"eventTypeName": "OneCustom",
"childrenEvents": []
}
]
}
]
}]
}
So I want to be able to get an object where the second parentEvent with parentEvent = null has became a root element, with an array childrenEvents, inside children array will be first parent event object with its own childrenEvents array and inside of this array I want to put existing root object with its own childrenEvents array
I appreciate if somebody could help me to resolve it. Thanks in advance.
My attempt
function rebuild(input)
{
var childrenEvents = [] ;
for ( f in input.parentEvent ) // we may have attributes other than "age"
if (f.parentEvent == null) {
f.parentEvent.push(childrenEvents);
}
else {
f.parentEvent.push(input.parentEvent[f]);
}
if (input.childrenEvents.length !== 0)
{
input.parentEvent[f].push(input.childrenEvents)
}
return input;
}
console.log(rebuild( $scope.myObj))
});
plunker
You could use an object to build all dependencies and take only the one with
parentEvent === null
as tree.
var my_obj = { "id": 22, "eventTypeId": 37, "eventTypeName": "CommonOnly", "parentEvent": { "id": 21, "eventTypeId": 35, "eventTypeName": "FullTest", "parentEvent": { "id": 20, "parentEvent": null, "eventTypeId": 38, "eventTypeName": "FullTest" } }, "childrenEvents": [{ "id": 24, "parentEventId": 22, "eventTypeId": 36, "eventTypeName": "BlindedTest", "childrenEvents": [] }, { "id": 23, "parentEventId": 22, "eventTypeId": 38, "eventTypeName": "OneCustom", "childrenEvents": [] }] },
tree = function (data, root) {
function iter(a) {
var parent;
if (a.childrenEvents && Array.isArray(a.childrenEvents)) {
a.childrenEvents.forEach(iter);
}
a.childrenEvents = o[a.id] && o[a.id].childrenEvents;
o[a.id] = a;
if (a.parentEvent === root) {
r = a;
} else {
if (a.parentEvent && 'id' in a.parentEvent) {
parent = a.parentEvent.id;
}
if ('parentEventId' in a) {
parent = a.parentEventId;
}
if (parent !== undefined) {
o[parent] = o[parent] || {};
o[parent].childrenEvents = o[parent].childrenEvents || [];
o[parent].childrenEvents.push(a);
}
}
if (a.parentEvent) {
iter(a.parentEvent);
delete a.parentEvent;
}
}
var r, o = {};
iter(data);
return r;
}(my_obj, null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The title of your question says "recursively" but there is no recursion (that I can see) in your code. Yo need to call rebuild() from within rebuild()... recursively.
Maybe something closer to this (haven't run it)...
function rebuild(input) {
var rslt = input; // If it stays this way, we've reached the end of the line
var parent = inpt.parentEvent;
if (parent) {
parent.childrenEvents = [];
parent.childrenEvents.push(input);
inpt.parentEventId = parent.id;
rslt = rebuild(parent);
}
return rslt;
}