javascript - struggling with normalisation using map and reduce -
i want radar chart have no control api output, have turn complicated data form. i'm stuck @ least half hour.
how can turn raw data
const raw = [{ "device_info": { "device_id": 123, "name": "iphone", }, "age_data": [{ "age_range": "0-10", "total_count": 15, "man": 6, "women": 9 }, { "age_range": "11-20", "total_count": 11, "man": 7, "women": 4 }] }, { "device_info": { "device_id": 456, "name": "android", }, "age_data": [{ "age_range": "0-10", "total_count": 1, "man": 1, "women": 0 }, { "age_range": "11-20", "total_count": 2, "man": 0, "women": 2 }] }]
into this
const data = [{ age_group: '0-20', iphone: 26, android: 3 }, { age_group: '21-30', iphone: 0, android: 0 }, ];
https://jsfiddle.net/cqmyganr/2
this have tried:
const age_group = raw[0].age_data.map(obj => ({ age_group: obj.age_range })) const cams = raw.map(obj => ({ device_id: obj.device_info.device_id, device_name: obj.device_info.name })) console.log(cams) const age_group_with_cams = age_group.map(obj => object.assign({}, obj, ...cams) ) console.log(age_group_with_cams)
after reading @webdeb's answer figured there better way did. here's came with:
const raw = [ { device_info: { device_id: 123 , name: "iphone" } , age_data: [ { age_range: "0-10" , total_count: 15 , man: 6 , women: 9 } , { age_range: "11-20" , total_count: 11 , man: 7 , women: 4 } ] } , { device_info: { device_id: 456 , name: "android" } , age_data: [ { age_range: "0-10" , total_count: 1 , man: 1 , women: 0 } , { age_range: "11-20" , total_count: 2 , man: 0 , women: 2 } ] } ]; // first, convert raw data relation: const relation = [], devices = {}; const toint = x => parseint(x, 10); (const { device_info: { device_id, name }, age_data } of raw) { devices[name] = 0; // default total_count of every device. (const { age_range, total_count, man, women } of age_data) { const [age_begin, age_end] = age_range.split("-").map(toint); relation.push({ device_id, name , age_begin, age_end , total_count, man, women }); } } // next, write function given age range returns stats: const getagerange = (begin, end) => relation.reduce((table, tuple) => { if (tuple.age_begin >= begin && tuple.age_end <= end) { const row = table.find(row => row.name === tuple.name); if (row) { row.total_count += tuple.total_count; row.man += tuple.man; row.women += tuple.women; } else table.push(object.assign({}, tuple)); } return table; }, []); // finally, create array of age groups we're looking for: const getagegroup = (begin, end) => getagerange(begin, end).reduce((summary, { name, total_count }) => { summary[name] = total_count; return summary; }, object.assign({ age_group: begin + "-" + end }, devices)); const data = [ getagegroup(0, 20) , getagegroup(21, 30) ]; console.log(data);
hopefully makes sense. tried stick relational model closely possible.
Comments
Post a Comment