Effective Javascript Exercise 5.2. Help organize thoughts
Query question: Using the sample data from this chapter, calculate the average age difference between mothers and children (the age of the mother when the child was born). You can use the middle function defined earlier in this chapter.
Note that not all mothers mentioned in the data are themselves present in the array. The byName object can be useful here, which makes it easy to find people object on their behalf.
JS File: http://eloquentjavascript.net/code/ancestry.js
My approach
-
Create an object with "mothers" as keys, with arrays containing "mother DOB, child name, daughter DOB".
-
Calculate mother's age at birth with daughter DOB - "mother of DOB"
-
Pass the values ββto the provided mean function written as
middle function (array) {function plus (a, b) {return a + b; } return array.reduce (plus) /array.length; }
I am stuck at step 1
Step 1 - subdivision
and. remove all data points where mother = null && & where the DOB's mother is unknown (her name is listed as "mother", but there is no separate entry for her)
Filter out all "null" entries:
var hasMom = ancestry.filter(function(person) {
return person.mother != null;});
Match an array of mothers only names:
var momSet = hasMom.map(function(person) {return person.mother;});
Create a function that will check if a record is contained in a set
function isInSet(set, person) {return set.indexOf(person.name) > -1};
Apply function in filter
var hasKnownMother = hasMom.filter(function(person)
{return isInSet(momSet, person)});
b. create byName object of these mothers with daughter and DOB
var byName = {};
hasKnownMother.forEach(function(person) {
byName[person.name] = [person.born, person.mother];});
QUESTION: so far I have filtered 34 records only 10. Cross-validating names and records, I am not getting expected results.
What am I doing wrong? What should I rethink?
from. search .JS file for mother name, add (press?) her DOB to byName object
QUESTION: I have no idea what to do if I want to look up the keys of the byName object (mothers names), map them to the ancestry.JS database keys, and add a .JS DOB entry to my byName object.
I think for a For In loop or binding?
source to share
I think the most efficient way would be to create a hash of people using the name as the key so that you don't constantly iterate. After that, you can iterate over the original array again, this time checking that the mother exists in the data and pushing the difference to the output array as you go.
var ancestryJSON = JSON.parse(ANCESTRY_FILE),
byName = {},
ageDifferences = [];
function initNameHash(){
for(var i = 0, len = ancestryJSON.length; i < len; i++){
byName[ancestryJSON[i].name] = ancestryJSON[i];
}
}
function setAgeDifferences(){
for(var i = 0, len = ancestryJSON.length; i < len; i++){
var child = ancestryJSON[i];
if(child.mother !== null &&
byName[child.mother] !== undefined){
var mother = byName[child.mother];
var ageDifference = child.born - mother.born;
ageDifferences.push(ageDifference);
}
}
}
function average(array) {
function plus(a, b) { return a + b; }
return array.reduce(plus) / array.length;
}
initNameHash();
setAgeDifferences();
console.log(ageDifferences);
alert(average(ageDifferences));
Check out the fiddle: https://jsfiddle.net/oafd8hgL/
source to share