I have an array of objects and I was trying to figure out how I can create a new array of objects that would display a new array of objects, but with an "occurences" field.
Here is my starting json array of objects:
const fakeJson = [
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
}
Example result of what I would like. Notice the for Country Canada, one of them has Occurences: 2 for Date_Available "2022-04-12". How would I be able to accomplish this?
const resultJSON = [
{
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada",
"Occurrences" : 1
},
{
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada",
"Ocurrences" : 1
},
{
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada",
"Occurrences" : 2
},
{
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China",
"Occurrences" : 1
}
Here is what I have so far. My idea was to create a temporary obj with the country name, date available and occurrence set default to 1. Then based on the Date_Available, increase by 1 every time it appeared. However, if China and Canada both have the same date, then it seems to mess up the code and does not properly print the result.
let countNameMapping = {};
let finalArr = [];
for(let i = 0; i < fakeJson.length; i++){
let tempObj = {Country:fakeJson[i].Country, Date_Available: fakeJson[i].Date_Available, occurence: 1};
let countryName = fakeJson[i].Country;
let date = fakeJson[i].Date_Available;
if(countNameMapping[date] === undefined){
countNameMapping[countryName] = tempObj;
} else {
countNameMapping[date].occurence += 1;
}
}
for(let k in countNameMapping){
finalArr.push(countNameMapping[k])
}
console.log(finalArr)
const json = fakeJson.reduce((prev, curr) => {
const check = () => prev.findIndex(({ Date_Available, Country }) =>
curr.Date_Available === Date_Available &&
curr.Country === Country
);
check() === -1
? prev.push({
...Object.fromEntries(
Object.entries(curr).filter(([key]) => !key.match(/id|name|age/i))
),
Occurences: 1 })
: prev[check()].Occurences++
return prev
}, [])
console.log({ json });
Group by a custom key, eg Date_Available + Country
reduce() the result, create an array with the first object as base, then add Ocurrences, based on the amount of objects found (.length)
const data = [{"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-10", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-11", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "China"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "Canada"}];
const grouped = data.reduce((p, c) => {
const key = c.Date_Available + c.Country;
(p[key] = p[key] || []).push(c);
return p;
}, {});
const result = Object.values(grouped).reduce((p, c) => [ ...p, { ...c[0], Ocurrences: c.length } ], []);
console.log(result)
Result:
[
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada",
"Ocurrences": 1
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada",
"Ocurrences": 1
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada",
"Ocurrences": 2
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China",
"Ocurrences": 1
}
]
you can use reduce and Object.values for that
like this
const groupBy = (data, ...keyGroup) => Object.values(data.reduce((res, item) => {
const key = keyGroup.map(k => item[k]).join('-')
const existing = res[key] || {...item, occurencies: 0}
return {
...res,
[key]: {...existing,occurencies: existing.occurencies + 1 }
}
}, {}))
const fakeJson = [
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-10",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-11",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "China"
},
{
"Id": 1,
"Name": "John",
"Age": 32,
"Date_Available": "2022-04-12",
"Popularity": 99,
"Country": "Canada"
}
]
console.log('by ID', groupBy(fakeJson, 'Id'))
console.log('by Country', groupBy(fakeJson, 'Country'))
console.log('by country and date', groupBy( fakeJson, 'Country', 'Date_Available'))
hello there is a json data as below.
var arr = [{
"ID": 1,
"parentID": 0,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
}, {
"ID": 2,
"parentID": 0,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet"
}, {
"ID": 3,
"parentID": 0,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria"
}, {
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes"
}, {
"ID": 5,
"parentID": 0,
"Phone": "(755) 968-6539",
"City": "Gönen",
"Name": "Madeson"
}, {
"ID": 6,
"parentID": 5,
"Phone": "(644) 892-5485",
"City": "Timkur",
"Name": "Rae"
}, {
"ID": 7,
"parentID": 0,
"Phone": "(896) 297-6568",
"City": "Louvain-la-Neuve",
"Name": "Celeste"
}, {
"ID": 8,
"parentID": 5,
"Phone": "(168) 452-3538",
"City": "Worksop",
"Name": "Rowan"
}, {
"ID": 9,
"parentID": 5,
"Phone": "(873) 337-9560",
"City": "Bad Neuenahr-Ahrweiler",
"Name": "Kendall"
}, {
"ID": 10,
"parentID": 0,
"Phone": "(450) 579-0491",
"City": "MIDdelburg",
"Name": "Madaline"
}, {
"ID": 11,
"parentID": 0,
"Phone": "(111) 162-2502",
"City": "Birecik",
"Name": "Chandler"
}, {
"ID": 12,
"parentID": 8,
"Phone": "(712) 483-3905",
"City": "Courbevoie",
"Name": "Craig"
}, {
"ID": 13,
"parentID": 8,
"Phone": "(872) 499-5833",
"City": "Cuccaro Vetere",
"Name": "Basia"
}, {
"ID": 14,
"parentID": 6,
"Phone": "(724) 797-0077",
"City": "Portree",
"Name": "Elmo"
}, {
"ID": 15,
"parentID": 5,
"Phone": "(366) 967-0433",
"City": "Dublin",
"Name": "Cairo"
}, {
"ID": 16,
"parentID": 11,
"Phone": "(147) 708-7321",
"City": "Rivière-du-Loup",
"Name": "Mannix"
}, {
"ID": 17,
"parentID": 0,
"Phone": "(407) 519-9894",
"City": "Roubaix",
"Name": "Justine"
}]
.
.
.
I wanted to make a treeview of this data and I got a result like the one below. No problem, it works properly.
[
{
"ID": 1,
"parentID": 0,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
},
{
"ID": 2,
"parentID": 0,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet",
"children": [
{
"ID": 30,
"parentID": 2,
"Phone": "(641) 756-7073",
"City": "Harrison Hot Springs",
"Name": "Hamilton",
"children": [
{
"ID": 54,
"parentID": 30,
"Phone": "(800) 876-5942",
"City": "Ribnitz-Damgarten",
"Name": "Kelsie",
"children": [
{
"ID": 62,
"parentID": 54,
"Phone": "(523) 159-2911",
"City": "Biała Podlaska",
"Name": "Clio"
}
]
},
{
"ID": 87,
"parentID": 30,
"Phone": "(500) 895-9220",
"City": "Piracicaba",
"Name": "Maya"
}
]
},
{
"ID": 40,
"parentID": 2,
"Phone": "(921) 336-7339",
"City": "Namur",
"Name": "Lionel"
},
{
"ID": 43,
"parentID": 2,
"Phone": "(410) 695-8540",
"City": "Saint-Laurent",
"Name": "Deanna",
"children": [
{
"ID": 63,
"parentID": 43,
"Phone": "(475) 190-5102",
"City": "Nicoya",
"Name": "Nola"
},
{
"ID": 98,
"parentID": 43,
"Phone": "(268) 572-5059",
"City": "San Marcello Pistoiese",
"Name": "Marny"
}
]
}
]
},
{
"ID": 3,
"parentID": 0,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria",
"children": [
{
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes",
"children": [
{
"ID": 44,
"parentID": 4,
"Phone": "(287) 866-8953",
"City": "Fiuminata",
"Name": "Darius",
"children": [
{
"ID": 47,
"parentID": 44,
"Phone": "(779) 411-0381",
"City": "Pontedera",
"Name": "Harding",
"children": [
{
"ID": 92,
"parentID": 47,
"Phone": "(925) 263-0254",
"City": "Curacaví",
"Name": "Aristotle"
}
]
}
]
},
{
"ID": 56,
"parentID": 4,
"Phone": "(963) 719-2718",
"City": "Gore",
"Name": "Rafael"
}
]
},
{
"ID": 58,
"parentID": 3,
"Phone": "(464) 318-7548",
"City": "Curepto",
"Name": "Leila"
}
]
.
.
.
My main question is parentID: I don't want to write parentID to objects that write 0. But when I remove the places that say parentID: 0, it doesn't work properly. Can you help?
The code I run is:
tree = function(array) {
var o = {
ID: 0
}
function arrGet(o) {
if (Array.isArray(o.children)) {
o.children.forEach(arrGet);
}
}
array.forEach(function(a) {
o[a.ID] = o[a.ID] || {
ID: a.ID,
parentID: a.parentID,
Phone: a.Phone,
City: a.City,
Name: a.Name
};
a.children = o[a.ID].children;
o[a.parentID] = o[a.parentID] || {
ID: a.parentID
};
o[a.parentID].children = o[a.parentID].children || [];
o[a.parentID].children.push(o[a.ID]);
});
arrGet(o[0]);
return o[0].children;
}(arr);
document.writeln('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
just find the way inside the tree, based on origin array...
Full code:
/*--------------------------------------------------------*\
| treeMaker : JSON [Array of obj] to Treeview (function) |
| |
| input array objets must be like { ID,[ parentID ] ...} |
\* -------------------------------------------------------*/
const treeMaker = arr =>
arr.reduce((tree,{parentID,...useful},_,Origin)=>
{
if (!parentID) tree.push({...useful}) // direct case!
else
{
let path = { children: tree } // path for insert
, road = [ Origin.find(x=>x.ID===parentID) ] // every road has an end
;
while(!!road[0].parentID) // as long as a parentID property exist
{
road.unshift(Origin.find(x=>x.ID===road[0].parentID)) // get road origin
}
for(let way of road) // make your way by following the road
{
path = path.children.find(x=>x.ID===way.ID) // change the path to children
}
if (!path.children) path.children = [] // if not exist, add children array
;
path.children.push({...useful}) // copy all useful items
}
return tree // back to the trees!
},[])
/*--------------------------------------------------------*/
// test part
const myArr =
[ { ID: 1, Phone: '(403) 125-2552', City: 'Coevorden', Name: 'Grady' }
, { ID: 2, Phone: '(979) 486-1932', City: 'Chełm', Name: 'Scarlet' }
, { ID: 3, Phone: '(573) 685-8350', City: 'Wardha', Name: 'Adria' }
, { ID: 4, parentID: 3, Phone: '(630) 292-9737', City: 'Villers-la-Loue', Name: 'Xerxes' }
, { ID: 5, Phone: '(755) 968-6539', City: 'Gönen', Name: 'Madeson' }
, { ID: 6, parentID: 5, Phone: '(644) 892-5485', City: 'Timkur', Name: 'Rae' }
, { ID: 7, Phone: '(896) 297-6568', City: 'Louvain-la-Neuve', Name: 'Celeste' }
, { ID: 8, parentID: 5, Phone: '(168) 452-3538', City: 'Worksop', Name: 'Rowan' }
, { ID: 9, parentID: 5, Phone: '(873) 337-9560', City: 'Bad Neuenahr-Ahrweiler', Name: 'Kendall' }
, { ID: 10, Phone: '(450) 579-0491', City: 'MIDdelburg', Name: 'Madaline' }
, { ID: 11, Phone: '(111) 162-2502', City: 'Birecik', Name: 'Chandler' }
, { ID: 12, parentID: 8, Phone: '(712) 483-3905', City: 'Courbevoie', Name: 'Craig' }
, { ID: 13, parentID: 8, Phone: '(872) 499-5833', City: 'Cuccaro Vetere', Name: 'Basia' }
, { ID: 14, parentID: 6, Phone: '(724) 797-0077', City: 'Portree', Name: 'Elmo' }
, { ID: 15, parentID: 5, Phone: '(366) 967-0433', City: 'Dublin', Name: 'Cairo' }
, { ID: 16, parentID: 11, Phone: '(147) 708-7321', City: 'Rivière-du-Loup', Name: 'Mannix' }
, { ID: 17, Phone: '(407) 519-9894', City: 'Roubaix', Name: 'Justine' }
, { ID: 18, parentID: 14, Phone: '(938) 793-5446', City: 'Eugene', Name: 'Dahlia' }
, { ID: 19, parentID: 5, Phone: '(425) 682-2189', City: 'Salisbury', Name: 'Irene' }
, { ID: 20, parentID: 12, Phone: '(351) 187-8200', City: 'Garaguso', Name: 'Trevor' }
, { ID: 21, Phone: '(601) 944-5214', City: 'Pointe-au-Pic', Name: 'Iris' }
, { ID: 22, parentID: 20, Phone: '(479) 532-6127', City: 'Salt Lake City', Name: 'Fleur' }
, { ID: 23, parentID: 19, Phone: '(339) 973-1695', City: 'Meldert', Name: 'Hayley' }
, { ID: 24, parentID: 11, Phone: '(946) 766-1649', City: 'Corral', Name: 'Baker' }
, { ID: 25, Phone: '(964) 413-7033', City: 'Joliet', Name: 'Leo' }
, { ID: 26, parentID: 7, Phone: '(898) 476-0059', City: 'Burntisland', Name: 'Rigel' }
]
const myTree = treeMaker ( myArr )
document.write('<pre>myTree:\n')
document.write(JSON.stringify(myTree,0,2))
document.write('</pre>')
In this algorithm, the destructuring assignment is used on each element of the original table, as follows:
let element1 = { ID:6, parentID:5, City:'Timkur', Name:'Rae' }
let {parentID, ...useful} = element1 // destructuring assignment
console.log( parentID ) // return 5
console.log( useful ) // return object { ID:6, City:'Timkur', Name:'Rae' }
console.log ( !parentID ) // return false
without parentID property:
let element2 = { ID:7, City:'Louvain-la-Neuve', Name: 'Celeste' }
let {parentID, ...useful} = element2 // destructuring assignment
console.log( parentID ) // undefined
console.log( useful ) // return object { ID:7, ....
console.log ( !parentID ) // return true
In this code the destructuring assignment is directly used inside the argument list of the array method reduce (see further)
About the use of the Array.reduce method (see mdn for more details):
const arr_tree = arr.reduce(function(tree,curr,idx,Origin) {…}, initilial_tree);
same as arrow notation:
a) const arr_tree = arr.reduce((tree,curr,_,Origin)=>{…}, []);
b) const arr_tree = arr.reduce((tree,{parentID,...useful},_,Origin)=>
Arrguments:
tree, array under construction (initialized by initilial_tree, here=[] =>empty array), this element must be returned at each iteration
curr: the current element (as in a loop on the array), **used in an destructuring assignment
{parentID,...useful} = curr ( please compare a) and b) )
idx: the index of the element (curr) on the array (not useful here and replaced by _)
Origin: the original table used by the method
the algorithm:
for any element with a parentID, its parent must be found in the tree under construction.
That is, for an X element with a parentID there is an X-1 element with that ID.
And if this X-1 element has itself a ParentID, there is also another X-2 element with this ID.
And so on, until we find an X-n element that has no ParentID.
This X-N element is directly at the root of the result array.
All that remains is to follow the reverse path in the tree structure under construction:
we look for the position Xn at the level of its root, then on this one the element X- (n-1) among its children, until finding that of the element X-1 where we can add the element X in the list of its children.
Making sure to add an empty list of children, if X-1 had no children yet.
There are therefore 2 parts:
1- go up the road from X-1 to the X-n elements using the origin table
let road = [ Origin.find(x=>x.ID===parentID) ] // every road has an end
while(!!road[0].parentID) // as long as a parentID property exist
{
road.unshift(Origin.find(x=>x.ID===road[0].parentID)) // get road origin
}
if we start from element X = { ID: 12, parentID: 8, ... Name: 'Craig'} (where the parentID value is 8)
the result is :
road = [ { ID: 5, ... Name: 'Madeson' }
, { ID: 8, parentID: 5,... Name: 'Rowan' }
]
note 1:
the use of the array.unshift() method to add the elements from the top
/ unlike the array.push() method, the last element entered is therefore in position zero,
which allows the test to be passed
(!!road[0].parentID)
with always an index value at zero.
...For the double exclamation mark look here
note 2:
the road array only contains "pointers" to the objects of the original array.
2- find the path of element X-1 in tree structure under construction
let path = { children: tree } // path for insert
for(let way of road) // make your way by following the road
{
path = path.children.find(x=>x.ID===way.ID) // change the path to children
}
note X: I use my sort of Whitesmiths style code formatting for years
for info, it's look like that:
├─1_Grady
├─2_Scarlet
├─3_Adria─┐
│ └─4_Xerxes
├─5_Madeson─┐
│ ├─6_Rae─┐
│ │ └─14_Elmo─┐
│ │ └─18_Dahlia
│ ├─8_Rowan─┐
│ │ ├─12_Craig─┐
│ │ │ └─20_Trevor─┐
│ │ │ └─22_Fleur
│ │ └─13_Basia
│ ├─9_Kendall
│ ├─15_Cairo
│ └─19_Irene─┐
│ └─23_Hayley
├─7_Celeste─┐
│ └─26_Rigel
├─10_Madaline
├─11_Chandler─┐
│ ├─16_Mannix
│ └─24_Baker
├─17_Justine
├─21_Iris
└─25_Leo
What you can do is to use the delete operator when parentID is equal to 0. This will delete the property from the object, hence not displaying it.
var arr = [{
"ID": 1,
"parentID": 0,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
}, {
"ID": 2,
"parentID": 0,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet"
}, {
"ID": 3,
"parentID": 0,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria"
}, {
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes"
}, {
"ID": 5,
"parentID": 0,
"Phone": "(755) 968-6539",
"City": "Gönen",
"Name": "Madeson"
}, {
"ID": 6,
"parentID": 5,
"Phone": "(644) 892-5485",
"City": "Timkur",
"Name": "Rae"
}, {
"ID": 7,
"parentID": 0,
"Phone": "(896) 297-6568",
"City": "Louvain-la-Neuve",
"Name": "Celeste"
}, {
"ID": 8,
"parentID": 5,
"Phone": "(168) 452-3538",
"City": "Worksop",
"Name": "Rowan"
}, {
"ID": 9,
"parentID": 5,
"Phone": "(873) 337-9560",
"City": "Bad Neuenahr-Ahrweiler",
"Name": "Kendall"
}, {
"ID": 10,
"parentID": 0,
"Phone": "(450) 579-0491",
"City": "MIDdelburg",
"Name": "Madaline"
}, {
"ID": 11,
"parentID": 0,
"Phone": "(111) 162-2502",
"City": "Birecik",
"Name": "Chandler"
}, {
"ID": 12,
"parentID": 8,
"Phone": "(712) 483-3905",
"City": "Courbevoie",
"Name": "Craig"
}, {
"ID": 13,
"parentID": 8,
"Phone": "(872) 499-5833",
"City": "Cuccaro Vetere",
"Name": "Basia"
}, {
"ID": 14,
"parentID": 6,
"Phone": "(724) 797-0077",
"City": "Portree",
"Name": "Elmo"
}, {
"ID": 15,
"parentID": 5,
"Phone": "(366) 967-0433",
"City": "Dublin",
"Name": "Cairo"
}, {
"ID": 16,
"parentID": 11,
"Phone": "(147) 708-7321",
"City": "Rivière-du-Loup",
"Name": "Mannix"
}, {
"ID": 17,
"parentID": 0,
"Phone": "(407) 519-9894",
"City": "Roubaix",
"Name": "Justine"
}];
tree = function(array) {
var o = {
ID: 0
}
function arrGet(o) {
if (Array.isArray(o.children)) {
o.children.forEach(arrGet);
}
}
array.forEach(function(a) {
o[a.ID] = o[a.ID] || {
ID: a.ID,
parentID: a.parentID,
Phone: a.Phone,
City: a.City,
Name: a.Name
};
if(a.parentID === 0)
delete o[a.ID].parentID;
a.children = o[a.ID].children;
o[a.parentID] = o[a.parentID] || {
ID: a.parentID
};
o[a.parentID].children = o[a.parentID].children || [];
o[a.parentID].children.push(o[a.ID]);
});
arrGet(o[0]);
return o[0].children;
}(arr);
document.writeln('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
var arr = [{
"ID": 1,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
}, {
"ID": 2,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet"
}, {
"ID": 3,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria"
}, {
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes"
}, {
"ID": 5,
"Phone": "(755) 968-6539",
"City": "Gönen",
"Name": "Madeson"
}, {
"ID": 6,
"parentID": 5,
"Phone": "(644) 892-5485",
"City": "Timkur",
"Name": "Rae"
}, {
"ID": 7,
"Phone": "(896) 297-6568",
"City": "Louvain-la-Neuve",
"Name": "Celeste"
}, {
"ID": 8,
"parentID": 5,
"Phone": "(168) 452-3538",
"City": "Worksop",
"Name": "Rowan"
}, {
"ID": 9,
"parentID": 5,
"Phone": "(873) 337-9560",
"City": "Bad Neuenahr-Ahrweiler",
"Name": "Kendall"
}, {
"ID": 10,
"Phone": "(450) 579-0491",
"City": "MIDdelburg",
"Name": "Madaline"
}, {
"ID": 11,
"Phone": "(111) 162-2502",
"City": "Birecik",
"Name": "Chandler"
}, {
"ID": 12,
"parentID": 8,
"Phone": "(712) 483-3905",
"City": "Courbevoie",
"Name": "Craig"
}, {
"ID": 13,
"parentID": 8,
"Phone": "(872) 499-5833",
"City": "Cuccaro Vetere",
"Name": "Basia"
}, {
"ID": 14,
"parentID": 6,
"Phone": "(724) 797-0077",
"City": "Portree",
"Name": "Elmo"
}, {
"ID": 15,
"parentID": 5,
"Phone": "(366) 967-0433",
"City": "Dublin",
"Name": "Cairo"
}, {
"ID": 16,
"parentID": 11,
"Phone": "(147) 708-7321",
"City": "Rivière-du-Loup",
"Name": "Mannix"
}, {
"ID": 17,
"Phone": "(407) 519-9894",
"City": "Roubaix",
"Name": "Justine"
}, {
"ID": 18,
"parentID": 14,
"Phone": "(938) 793-5446",
"City": "Eugene",
"Name": "Dahlia"
}, {
"ID": 19,
"parentID": 5,
"Phone": "(425) 682-2189",
"City": "Salisbury",
"Name": "Irene"
}, {
"ID": 20,
"parentID": 12,
"Phone": "(351) 187-8200",
"City": "Garaguso",
"Name": "Trevor"
}, {
"ID": 21,
"Phone": "(601) 944-5214",
"City": "Pointe-au-Pic",
"Name": "Iris"
}, {
"ID": 22,
"parentID": 20,
"Phone": "(479) 532-6127",
"City": "Salt Lake City",
"Name": "Fleur"
}, {
"ID": 23,
"parentID": 19,
"Phone": "(339) 973-1695",
"City": "Meldert",
"Name": "Hayley"
}, {
"ID": 24,
"parentID": 11,
"Phone": "(946) 766-1649",
"City": "Corral",
"Name": "Baker"
}, {
"ID": 25,
"Phone": "(964) 413-7033",
"City": "Joliet",
"Name": "Leo"
}, {
"ID": 26,
"parentID": 7,
"Phone": "(898) 476-0059",
"City": "Burntisland",
"Name": "Rigel"
}]
original data like this
I have JSON like below, I need to filter out workers having the age less than 25.
var employee = {
"value": [
{
"position": "Seniro Developer",
"description": "Developemwnt",
"workers": [
{
"name": "Kumar",
"age": 22
},
{
"name": "aravinth",
"age": 29
},
{
"name": "sathish",
"age": 35
}
]
},
{
"position": "Tester",
"description": "testing",
"workers": [
{
"name": "vinth",
"age": 18
},
{
"name": "rahul",
"age": 45
},
{
"name": "sathish",
"age": 12
}
]
}
]
}
I have tried to use the below code, but it returns all the value inside the workers array, but my expectation is it should return only the employee having than 25.
If I use Map function it is affecting the employee Object also.
var filteredResult = employee.filter(e => e.workers.some(w => w.age < 25))
Expected Result:
{
"value": [
{
"position": "Seniro Developer",
"description": "Developemwnt",
"workers": [
{
"name": "Kumar",
"age": 22
}
]
},
{
"position": "Tester",
"description": "testing",
"workers": [
{
"name": "vinth",
"age": 18
},
{
"name": "sathish",
"age": 12
}
]
}
]
}
You can do it with a map and a filter, to avoid to modify the original array, you can use Object.asign
var employee = {
"value": [{
"position": "Seniro Developer",
"description": "Developemwnt",
"workers": [{
"name": "Kumar",
"age": 22
},
{
"name": "aravinth",
"age": 29
},
{
"name": "sathish",
"age": 35
}
]
},
{
"position": "Tester",
"description": "testing",
"workers": [{
"name": "vinth",
"age": 18
},
{
"name": "rahul",
"age": 45
},
{
"name": "sathish",
"age": 12
}
]
}
]
}
var filteredResult = employee.value.map(e => {
let filter = e.workers.filter(w => w.age < 25)
return Object.assign({}, e, {workers: filter})
})
console.log('original', employee)
console.log('result', filteredResult)
You could reduce the array and check if the filtered workers have some elements then push a new object with changed workers to the result set.
var employee = { value: [{ position: "Seniro Developer", description: "Developemwnt", workers: [{ name: "Kumar", age: 22 }, { name: "aravinth", age: 29 }, { name: "sathish", age: 35 }] }, { position: "Tester", description: "testing", workers: [{ name: "vinth", age: 18 }, { name: "rahul", age: 45 }, { name: "sathish", age: 12 }] }] },
value = employee.value.reduce((r, o) => {
const workers = o.workers.filter(({ age }) => age < 25);
if (workers.length) r.push({ ...o, workers });
return r;
}, []),
result = { value };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can also try this:
var employee = { "value": [ { "position": "Seniro Developer", "description": "Developemwnt", "workers": [ { "name": "Kumar", "age": 22 }, { "name": "aravinth", "age": 29 }, { "name": "sathish", "age": 35 } ] }, { "position": "Tester", "description": "testing", "workers": [ { "name": "vinth", "age": 18 }, { "name": "rahul", "age": 45 }, { "name": "sathish", "age": 12 } ] } ]}
result = employee.value.map(({workers, ...rest})=>({...rest, workers:[...workers.filter(k=>k.age<25)]}));
console.log(result);
Use map and while creating the workers key in return object use filter to get employee with age less than 25. map will create an array
var employee = {
"value": [{
"position": "Seniro Developer",
"description": "Developemwnt",
"workers": [{
"name": "Kumar",
"age": 22
},
{
"name": "aravinth",
"age": 29
},
{
"name": "sathish",
"age": 35
}
]
},
{
"position": "Tester",
"description": "testing",
"workers": [{
"name": "vinth",
"age": 18
},
{
"name": "rahul",
"age": 45
},
{
"name": "sathish",
"age": 12
}
]
}
]
}
let filteredEmployee = employee.value.map((item) => {
return {
"position": item.position,
"description": item.description,
"workers": item.workers.filter(elem => elem.age < 25)
}
});
let newObject = Object.assign({}, {
value: filteredEmployee
});
console.log(newObject)
You can use map method with ... rest syntax:
employee.value.map(({workers, ...rest}) => ({...rest,
workers: workers.filter(w => w.age < 25)}));
An example:
let employee = {
"value": [
{
"position": "Seniro Developer",
"description": "Developemwnt",
"workers": [
{
"name": "Kumar",
"age": 22
},
{
"name": "aravinth",
"age": 29
},
{
"name": "sathish",
"age": 35
}
]
},
{
"position": "Tester",
"description": "testing",
"workers": [
{
"name": "vinth",
"age": 18
},
{
"name": "rahul",
"age": 45
},
{
"name": "sathish",
"age": 12
}
]
}
]
}
const result = employee.value.map(({workers, ...rest}) => ({...rest, workers: workers.filter(w => w.age < 25)}));
console.log(result);
This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I have a JSON data with the following format:
activities
[
{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
"items": [
{
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}
]
},
{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": [
{
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
},
{
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}
]
},
{
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": [
{
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}
]
}
]
I want to reformat this data using lodash or simply javascript to look like this:
/*poi_id is the key*/
"1": [{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
"items": {
/*due_date is the key*/
"2016-09-08T18:15:00.000Z": [{
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}]
}
}, {
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": {
"2016-09-27T18:15:00.000Z": [{
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}]
}
}],
"9": [{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": {
"2016-09-14T18:15:00.000Z": [{
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
}, {
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}]
}
}]
All I want is to put the data that has the same poi_id under one collection with the key of poi_id and same for the items with same due_date.
Here's what I've done so far:
let activityArray = {};
_.forEach(activities, (activityItem) => {
if (!activityArray[activityItem.poi_id]) {
activityArray[activityItem.poi_id] = [];
}
activityArray[activityItem.poi_id].push(activityItem);
_.forEach(activityArray[activityItem.poi_id], (value, key) => {
activityArray[activityItem.poi_id][key].items.unshift(activityArray[activityItem.poi_id][key].due_date);
});
});
And this is what I got:
"1": [{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
/*unShift added due_date twice here, I want here key value pair*/
"items": [
"2016-09-08T18:15:00.000Z",
"2016-09-08T18:15:00.000Z", {
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}
]
}, {
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": [
"2016-09-27T18:15:00.000Z", {
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}
]
}],
"9": [{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": [
"2016-09-14T18:15:00.000Z", {
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
}, {
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}
]
}]
I tried with other approaches too, but couldn't make it like the one I'm expecting.
Please guide me here.
Thanks.
A compact solution in plain Javascript with an object as hash for the items arrays.
var activities = [{ "id": 32, "poi_id": 1, "due_date": "2016-09-08T18:15:00.000Z", "items": [{ "id": 21, "name": "Choluv jar : JAR", "activity_id": 32 }] }, { "id": 30, "poi_id": 9, "due_date": "2016-09-14T18:15:00.000Z", "items": [{ "id": 17, "name": "Bourbon Family : PKT", "activity_id": 30 }, { "id": 18, "name": "Choluv jar : JAR", "activity_id": 30 }] }, { "id": 29, "poi_id": 1, "due_date": "2016-09-27T18:15:00.000Z", "items": [{ "id": 16, "name": "Choluv jar : JAR", "activity_id": 29 }] }],
hash = {},
grouped = {};
activities.forEach(a => {
hash[a.poi_id] = hash[a.poi_id] || {};
hash[a.poi_id][a.due_date] = hash[a.poi_id][a.due_date] || [];
grouped[a.poi_id] = grouped[a.poi_id] || [];
grouped[a.poi_id].push({
id: a.id,
poi_id: a.poi_id,
due_date: a.due_date,
items: { [a.due_date]: hash[a.poi_id][a.due_date] }
});
a.items.forEach(b => hash[a.poi_id][a.due_date].push(b));
});
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }