recursively transform json object - javascript

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

Related

Dynamically delete multiple columns from array

I am trying to figure out how to delete multiple column from an array of objects based on a dynamically selected list of values.
If I want to delete a specific column, I can do something like below.
Assuming array is:
list = [
{
"THEDATE": "12/11/2022",
"E38": 247,
"E40": 212,
"N45": 139,
"N48:: 10
},
{
"THEDATE": "12/10/2022",
"E38": 47,
"E40": 22,
"N45": 19,
"N48:: 66
},
{
"THEDATE": "12/12/2022",
"E38": 24,
"E40": 21,
"N45": 39,
"N48": 34
},
]
If I want to remove "N45", I can use:
let new_list = list.map(function (obj) {
return {
"THEDATE": obj.TheDate,
"E38": obj.e38,
"E40": obj.e40,
"N48": obj.n48
}
}
But if I have a list of column to remove, how would I modify the code?
Assuming
var colToRemove = ["N45", "E38"];
Update - Attempting IE 11 Version
I tried to convert the arrow function to a regular function that IE 11 can understand but I get "colToRemove.has is not a function".
var colToRemove = $(allErrCodes).not(selErrCodes).get();
const altered = list.map(
function (item) {
blah = Object.keys(item).reduce(function (acc, key) {
if (!colToRemove.has(key)) acc[key] = item[key]; return acc;
}, {})
}
);
You could reduce the valid keys for each item into a new object.
const main = () => {
const altered = list.map(item =>
Object.keys(item).reduce((acc, key) => {
if (!colToRemove.has(key)) acc[key] = item[key];
return acc;
}, {}));
console.log(altered);
};
const colToRemove = new Set(["N45", "E38"]);
const list = [{
"THEDATE": "12/11/2022",
"E38": 247,
"E40": 212,
"N45": 139,
"N48": 10
}, {
"THEDATE": "12/10/2022",
"E38": 47,
"E40": 22,
"N45": 19,
"N48": 66
}, {
"THEDATE": "12/12/2022",
"E38": 24,
"E40": 21,
"N45": 39,
"N48": 34
}];
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }
If you want to modify the items in-place, you can delete:
Note: Be aware that this mutates the object, rather than creating a copy
const main = () => {
list.forEach(item =>
Object.keys(item).forEach(key => {
if (colToRemove.has(key)) {
delete item[key];
}
}));
console.log(list);
};
const colToRemove = new Set(["N45", "E38"]);
const list = [{
"THEDATE": "12/11/2022",
"E38": 247,
"E40": 212,
"N45": 139,
"N48": 10
}, {
"THEDATE": "12/10/2022",
"E38": 47,
"E40": 22,
"N45": 19,
"N48": 66
}, {
"THEDATE": "12/12/2022",
"E38": 24,
"E40": 21,
"N45": 39,
"N48": 34
}];
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }
Here is an IE compatible script:
function main() {
var altered = list.map(function(item) {
return Object.keys(item).reduce(function(acc, key) {
if (colToRemove.indexOf(key) === -1) {
acc[key] = item[key];
}
return acc;
}, {})
});
console.log(altered);
};
var colToRemove = ["N45", "E38"];
var list = [{
"THEDATE": "12/11/2022",
"E38": 247,
"E40": 212,
"N45": 139,
"N48": 10
}, {
"THEDATE": "12/10/2022",
"E38": 47,
"E40": 22,
"N45": 19,
"N48": 66
}, {
"THEDATE": "12/12/2022",
"E38": 24,
"E40": 21,
"N45": 39,
"N48": 34
}];
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

How to filter javascript object with dynamic filter

I have a javascript object, and array of id's:
var ids = [46,44,49,47];
var obj = {
"46": {
"group": "A",
"temp": 26,
"humid": 36
},
"44": {
"group": "B",
"temp": 19,
"humid": 32
},
"49": {
"group": "B",
"temp": 20,
"humid": 31
},
"47": {
"group": "A",
"temp": 24,
"humid": 32
}
};
I want to get the average 'temp' of each 'group'. How can I do this?
I found other examples that would solve this problem, however, these examples assume that 'group' will always be the same. In my case, 'group' is always changing.
So essentially I need to find how many unique groups exist, then return the average 'temp' value of each.
I attempted to use some for loops nested together, but it got complicated quickly...
Expected Output:
avgTemps = {"A":25, "B": 19.5}
In a first step, you obtain a list of unique group names present in the data. Then, you filter out the temperatures for each group and compute the average.
You can also use lodash functions for removing duplicate entries from a list (_.uniq) and to sum an array of numbers (_.sum).
var ids = [46,44,49,47];
var obj = {
"46": {
"group": "A",
"temp": 26,
"humid": 36
},
"44": {
"group": "B",
"temp": 19,
"humid": 32
},
"49": {
"group": "B",
"temp": 20,
"humid": 31
},
"47": {
"group": "A",
"temp": 24,
"humid": 32
}
};
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
let groups = Object.values(obj).map((o)=>o.group).filter(onlyUnique)
for (let group of groups) {
let temps = Object.values(obj).filter((o)=>o.group===group).map((o)=>o.temp)
let avgtmp = temps.reduce((pv, cv) => pv + cv, 0)/temps.length;
console.log(`group ${group} has an avg tmp of ${avgtmp}`)
}
// OUTPUT
// group B has an avg tmp of 19.5
// group A has an avg tmp of 25
You can use Object.keys(obj) to get each ids of the group.
Then you can get values from this group like this:
const obj = {
"46": {
"group": "A",
"temp": 26,
"humid": 36
},
"44": {
"group": "B",
"temp": 19,
"humid": 32
},
"49": {
"group": "B",
"temp": 20,
"humid": 31
},
"47": {
"group": "A",
"temp": 24,
"humid": 32
}
};
Object.keys(obj).map((id) => console.log(`Temp of id ${id} is ${obj[id].temp}`))
We can create the object with group values.
Now if you can map your obj, let's create the average value of each group.
const obj = {
"46": {
"group": "A",
"temp": 26,
"humid": 36
},
"44": {
"group": "B",
"temp": 19,
"humid": 32
},
"49": {
"group": "B",
"temp": 20,
"humid": 31
},
"47": {
"group": "A",
"temp": 24,
"humid": 32
}
};
const groups = {};
Object.keys(obj).map((id) => {
if(!!groups[obj[id].group]) {
groups[obj[id].group].push(obj[id].temp);
} else {
groups[obj[id].group] = [obj[id].temp]
}
})
console.log(groups)
Then finally we can count average temps.
const obj = {
"46": {
"group": "A",
"temp": 26,
"humid": 36
},
"44": {
"group": "B",
"temp": 19,
"humid": 32
},
"49": {
"group": "B",
"temp": 20,
"humid": 31
},
"47": {
"group": "A",
"temp": 24,
"humid": 32
}
};
const groups = {};
Object.keys(obj).forEach((id) => {
if(!!groups[obj[id].group]) {
groups[obj[id].group].push(obj[id].temp);
} else {
groups[obj[id].group] = [obj[id].temp]
}
})
function getAvg(grades) {
const total = grades.reduce((acc, c) => acc + c, 0);
return total / grades.length;
}
Object.keys(groups).forEach((group) => {
groups[group] = getAvg(groups[group])
})
console.log(groups)
This should be a little bit shorter:
let output = {};
for (let group in obj) {
const groupName = obj[group]['group'];
if(!output[groupName]) {
output[groupName] = obj[group]['temp'];
} else {
output[groupName] = (output[groupName] + obj[group]['temp'])/2;
}
}
console.log(output);
Create the target object first with sums and counts, and then divide those to averages:
function getAvgTemp(obj) {
let data = Object.values(obj);
let result = Object.fromEntries(data.map(({group}) => [group, { sum: 0, count: 0 }]));
for (let {group, temp} of data) {
let o = result[group];
o.count++;
o.sum += temp;
}
for (let key of Object.keys(result)) {
result[key] = result[key].sum / result[key].count;
}
return result;
}
// Demo
var obj = {"46": {"group": "A","temp": 26,"humid": 36},"44": {"group": "B","temp": 19,"humid": 32},"49": {"group": "B","temp": 20,"humid": 31},"47": {"group": "A","temp": 24,"humid": 32}};
let avgTemp = getAvgTemp(obj);
console.log(avgTemp);
Note that the ids array seems overkill, since the properties of the object can be collected with Object.keys.
One more example in functional style)
function avg(vals: number[]): number {
return vals.reduce((a, b) => a + b) / vals.length;
}
function groupBy<Item, Desc extends string | number>(descriminator: (item: Item) => Desc) {
return (items: Item[]): Record<Desc, Item[]> => items.reduce((groups, item) => ({
...groups,
[descriminator(item)]: [...(groups[descriminator(item)] || []), item]
}), {} as Record<Desc, Item[]>);
}
function mapValues<From, To>(mapper: (from: From) => To) {
return (record: Record<string, From>): Record<string, To> => Object.assign(
{} as Record<string, To>,
...Object.keys(record).map(key => ({
[key]: mapper(record[key])
}))
)
}
const groups = groupBy(
({ group }: Item) => group
)(
Object.values(obj)
);
const avgTemps = mapValues(
(groupItems: Item[]) => avg(groupItems.map(({ temp }) => temp))
)(
groups
);
TS Playground
First of all, I have taken all the unique groups in a set for distinction. Then created an array of objects is manipulated and eventually all the average, count, and the total is assigned in the array of objects. And the expected result is generated.
var ids = [46, 44, 49, 47];
var obj = {
"46": {
"group": "A",
"temp": 26,
"humid": 36
},
"44": {
"group": "B",
"temp": 19,
"humid": 32
},
"49": {
"group": "B",
"temp": 20,
"humid": 31
},
"47": {
"group": "A",
"temp": 24,
"humid": 32
}
};
var groups = new Set()
Object.keys(obj).forEach(element => {
groups.add(obj[element].group);
});
var tempAvgByGroups = [];
const avgTemp = {}
groups.forEach(element => {
const groupObj = {
"group": element,
"average": 0,
"count": 0,
"total": 0,
}
Object.keys(obj).forEach(item => {
if (element === obj[item]["group"]) {
groupObj["count"] = groupObj["count"] + 1;
groupObj["total"] = groupObj["total"] + obj[item]["temp"]
}
});
groupObj["average"] = groupObj["total"] / groupObj["count"];
tempAvgByGroups.push(groupObj);
avgTemp[element] = groupObj["average"]
});
console.log(avgTemp);
you can do that:
const
ids = [46,44,52,49,47]
, obj =
{ '46': { group: 'A', temp: 26, humid: 36 }
, '44': { group: 'B', temp: 19, humid: 32 }
, '49': { group: 'B', temp: 20, humid: 31 }
, '47': { group: 'A', temp: 24, humid: 32 }
, '64': { group: 'A', temp: 25, humid: 32 }
}
, avgTemps =
ids.reduce((rO,key)=>{if (obj[key]) rO.push(obj[key]);return rO},[])
.reduce((res,o,_,Oe)=>
{
if(!res[o.group])
{
let grp = Oe.filter(x=>x.group===o.group)
.map(y=>y.temp)
res[o.group] = grp.reduce((sum,t)=>sum+t,0) / grp.length
}
return res
},{})
console.log( avgTemps )
.as-console-wrapper {max-height: 100%!important;top:0 }

Extract items from a json file with values in an array

I am trying to handle JSON arrays to extract key value pair from the keys available from user selection.
This is not real time json example...It is just a sample
Example of JSON
var personnel = [
{
id: 5,
name: "Luke Skywalker",
pilotingScore: 98,
shootingScore: 56,
isForceUser: true,
},
{
id: 82,
name: "Sabine Wren",
pilotingScore: 73,
shootingScore: 99,
isForceUser: false,
skills:{
'skill1':'vision',
'skill2':'strength'
}
},
{
id: 22,
name: "Zeb Orellios",
pilotingScore: 20,
shootingScore: 59,
isForceUser: false,
},
{
id: 15,
name: "Ezra Bridger",
pilotingScore: 43,
shootingScore: 67,
isForceUser: true,
skills:{
'skill1':'vision',
'skill2':'strength'
}
},
{
id: 11,
name: "Caleb Dume",
pilotingScore: 71,
shootingScore: 85,
isForceUser: true,
},
];
sample_arr = [id,name,skills.skill1];
let op = personnel.map(md => {
return { id: md.id,name:md.name,skills{skill1:md.skills.skill1}};
});
console.log(JSON.stringify(op,null,2))
I wanted to get key value pair like below.
[
{
"id": 5,
"name": "Luke Skywalker"
},
{
"id": 82,
"name": "Sabine Wren",
"skills":{
"skill1": 'vision'
}
},
{
"id": 22,
"name": "Zeb Orellios"
},
{
"id": 15,
"name": "Ezra Bridger"
},
{
"id": 11,
"name": "Caleb Dume"
}
]
I now updated the my problem statement.
Requirement:
Extract all JSON values selected by the user to a new array. This will save more time as the json is 700MB all the way and it is time consuming to handle on every request
You have the user selections stored in the array? If so, you could do something like:
let sample_arr = ['id', 'name']
let op = personnel.map(md => {
let user = {}
sample_arr.forEach(val => {
if (md[val]) {
user[val] = md[val]
}
})
return user
})
Here's a simple function to do this:
const project = (keys) => (xs) =>
xs .map (x => keys .reduce ( (a, k) => ({...a, [k]: x[k]}), {} ))
var personnel = [{id:5,name:"Luke Skywalker",pilotingScore:98,shootingScore:56,isForceUser:true},{id:82,name:"Sabine Wren",pilotingScore:73,shootingScore:99,isForceUser:false,skills:{skill1:"vision",skill2:"strength"}},{id:22,name:"Zeb Orellios",pilotingScore:20,shootingScore:59,isForceUser:false},{id:15,name:"Ezra Bridger",pilotingScore:43,shootingScore:67,isForceUser:true,skills:{skill1:"vision",skill2:"strength"}},{id:11,name:"Caleb Dume",pilotingScore:71,shootingScore:85,isForceUser:true}];
console .log (
project (['id', 'name']) (personnel)
)
The name project is from Codd's early papers on relational databases; it's similar in feel to SQL's select statement.
Update
The answer from KellyKapoor has one feature the above lacks: it only includes the property name if the data has it (so no skills: undefined.)
It's not clear which behavior the OP is looking for, but this minor modification offers that feature
const project2 = (keys) => (xs) =>
xs .map (x => keys .reduce ((a, k) => ({...a, ...(k in x ? {[k]: x[k]} : {}) }), {} ))
var personnel = [{id:5,name:"Luke Skywalker",pilotingScore:98,shootingScore:56,isForceUser:true},{id:82,name:"Sabine Wren",pilotingScore:73,shootingScore:99,isForceUser:false,skills:{skill1:"vision",skill2:"strength"}},{id:22,name:"Zeb Orellios",pilotingScore:20,shootingScore:59,isForceUser:false},{id:15,name:"Ezra Bridger",pilotingScore:43,shootingScore:67,isForceUser:true,skills:{skill1:"vision",skill2:"strength"}},{id:11,name:"Caleb Dume",pilotingScore:71,shootingScore:85,isForceUser:true}];
console .log (
project2 (['id', 'name', 'skills']) (personnel)
)
Whats the problem with this?
let op = personnel.map(md => {
return { id: md.id,name:md.name};
});
You can create a function which extracts the props from an object based on a passed array of keys:
var data = [ { id: 5, name: "Luke Skywalker", pilotingScore: 98, shootingScore: 56, isForceUser: true, }, { id: 82, name: "Sabine Wren", pilotingScore: 73, shootingScore: 99, isForceUser: false, skills:{ 'skill1':'vision', 'skill2':'strength' } }, { id: 22, name: "Zeb Orellios", pilotingScore: 20, shootingScore: 59, isForceUser: false, }, { id: 15, name: "Ezra Bridger", pilotingScore: 43, shootingScore: 67, isForceUser: true, skills:{ 'skill1':'vision', 'skill2':'strength' } }, { id: 11, name: "Caleb Dume", pilotingScore: 71, shootingScore: 85, isForceUser: true, }, ];
let pick = (obj, fields) => Object.keys(obj)
.reduce((r,c) => (fields.includes(c) ? r[c] = obj[c] : null, r), {})
let result = data.map(x => pick(x, ['id', 'name', 'skills']))
console.log(result)
Then all you need is to loop though via Array.map to pick from all objects.

Group or summarize Javascript array

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

return array of object javascript

With this array:
var booksStudents = [
{
name: "David",
books: {
"fantasy": 23,
"action": 31,
"thriller" 21,
}
},
name: "Paul",
books: {
"fantasy": 17,
"action": 13,
"thriller" 23,
}
},
name: "Zoe",
books: {
"fantasy": 5,
"action": 7,
"thriller" 28,
}
}];
I would like to return an array of objects, each containing the name of a person and the sum of all their respective books.
I know how to use the reduce method on a simple array but I am stuck with this array of object.
I was thinking of using .map and .reduce but I did not find something interesting.
booksStudents = booksStudents.map(function(item){
var count = 0;
for(var key in item.books){
count+=item.books[key];
}
item.count = count;
return item;
})
use map and for..in to count the number.
Firstly there are few mistakes in your array of objects, Let me point them.
var booksStudents = [
{
name: "David",
books: {
"fantasy": 23,
"action": 31,
"thriller": 21, // : missing
}
},
{ // { missing
name: "Paul",
books: {
"fantasy": 17,
"action": 13,
"thriller": 23, // : missing
}
},
{ // { missing
name: "Zoe",
books: {
"fantasy": 5,
"action": 7,
"thriller": 28, // : missing
}
}];
So now after this is fixed the solution to get your end result is by using this code.
var newArray = [];
$.each(booksStudents,function(index,value){
var currObj = {};
currObj.name= this.name;
currObj.totalBooks = parseInt(this.books.fantasy) +parseInt(this.books.action)+parseInt(this.books.thriller) ;
newArray.push(currObj);
});
console.log(newArray);
Here is a Wroking Fiddle check console for output
The output is as below .

Categories