Kayla Larson
Kayla Larson

Reputation: 45

Data manipulation with a double data set

Return an object where each key is an instructor name and each value is an array of the modules they can teach based on their skills.

Here are the datasets I am supposed to manipulate through:

const instructors = [
  { name: 'Pam', module: 2, teaches: ['scope', 'recursion', 'node'] },
  { name: 'Brittany', module: 2, teaches: ['oop', 'pwas'] },
  { name: 'Nathaniel', module: 2, teaches: ['oop', 'scope', 'mobile'] },
  { name: 'Robbie', module: 4, teaches: ['node', 'pwas'] },
  { name: 'Leta', module: 4, teaches: ['pwas', 'node', 'recursion'] },
  { name: 'Travis', module: 1, teaches: ['javascript', 'html', 'css'] },
  { name: 'Louisa', module: 1, teaches: ['javascript', 'html', 'css', 'node', 'pwas'] },
  { name: 'Christie', module: 3, teaches: ['javascript', 'react', 'node'] },
  { name: 'Will', module: 3, teaches: ['javascript', 'redux', 'react', 'oop', 'scope'] }
];

const cohorts = [
  { cohort: 1806, module: 1, studentCount: 30, curriculum: ['html', 'css', 'javascript'] },
  { cohort: 1804, module: 2, studentCount: 21, curriculum: ['javascript', 'css', 'recursion', 'scope', 'oop'] },
  { cohort: 1803, module: 3, studentCount: 20, curriculum: ['react', 'redux', 'html', 'javascript'] },
  { cohort: 1801, module: 4, studentCount: 18, curriculum: ['pwas', 'mobile', 'node', 'javascript', 'css'] }
];

Below is the code I have tried, I keep having issues iterating through two data sets, linking them together is tough!

This is what I've tried but cannot get the correct arrays to appear as values in the object:

let result1 = instructors.reduce((teacherObj, teacherName) => {
  if(!teacherObj[teacherName.name]) {
    teacherObj[teacherName.name] = []
    // console.log(instructors.map(a => a.module))
  }

  return teacherObj
}, {})
console.log(result1)

Expected Result:

{
   Pam: [2, 4],
   Brittany: [2, 4],
   Nathaniel: [2, 4],
   Robbie: [4],
   Leta: [2, 4],
   Travis: [1, 2, 3, 4],
   Louisa: [1, 2, 3, 4],
   Christie: [1, 2, 3, 4],
   Will: [1, 2, 3, 4]
}

Upvotes: 3

Views: 44

Answers (2)

3limin4t0r
3limin4t0r

Reputation: 21130

After working out the answer for myself the result is basically the same as the answer of CertainPerformance.

I opted to use Set as the value in the lookup hash, to directly eliminate duplicates when they are added. My version also uses another technique for flattening the array. I concat the array using reduce, instead of spreading the array into a concat call.

const instructors = [{name: 'Pam', module: 2, teaches: ['scope', 'recursion', 'node']}, {name: 'Brittany', module: 2, teaches: ['oop', 'pwas']}, {name: 'Nathaniel', module: 2, teaches: ['oop', 'scope', 'mobile']}, {name: 'Robbie', module: 4, teaches: ['node', 'pwas']}, {name: 'Leta', module: 4, teaches: ['pwas', 'node', 'recursion']}, {name: 'Travis', module: 1, teaches: ['javascript', 'html', 'css']}, {name: 'Louisa', module: 1, teaches: ['javascript', 'html', 'css', 'node', 'pwas']}, {name: 'Christie', module: 3, teaches: ['javascript', 'react', 'node']}, {name: 'Will', module: 3, teaches: ['javascript', 'redux', 'react', 'oop', 'scope']}];
const cohorts = [{cohort: 1806, module: 1, studentCount: 30, curriculum: ['html', 'css', 'javascript']}, {cohort: 1804, module: 2, studentCount: 21, curriculum: ['javascript', 'css', 'recursion', 'scope', 'oop']}, {cohort: 1803, module: 3, studentCount: 20, curriculum: ['react', 'redux', 'html', 'javascript']}, {cohort: 1801, module: 4, studentCount: 18, curriculum: ['pwas', 'mobile', 'node', 'javascript', 'css']}];

// prepare module lookup hash
let moduleLookup = {};
cohorts.forEach(({module, curriculum}) => {
  curriculum.forEach(craft => {
    let modules = moduleLookup[craft] || (moduleLookup[craft] = new Set());
    modules.add(module);
  });
});

// answer
let result = {};
instructors.forEach(({name, teaches}) => {
  let modules = teaches
    .map(craft => Array.from(moduleLookup[craft])) // get modules for each craft
    .reduce((acc, arr) => acc.concat(arr), []); // flatten 1 level

  result[name] = Array.from(new Set(modules)); // remove duplicates
});

console.log(result);

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370809

First transform the cohorts array into an object indexed by curriculum, whose values are that curriculum's associated module(s), allowing for quick lookup. That is, an object like:

// modulesByCurriculum
{
  "html": [    // html is present in module 1 and 3
    1,
    3
  ],
  "css": [     // css is present in modules 1, 2, and 4
    1,
    2,
    4
  ], ...

This allows you to take a program name, like scope, and get its associated modules quickly.

Then, iterate through the instructors and look up each associated curriculum to find the modules, deduplicating via a Set:

const instructors = [
  { name: 'Pam', module: 2, teaches: ['scope', 'recursion', 'node'] },
  { name: 'Brittany', module: 2, teaches: ['oop', 'pwas'] },
  { name: 'Nathaniel', module: 2, teaches: ['oop', 'scope', 'mobile'] },
  { name: 'Robbie', module: 4, teaches: ['node', 'pwas'] },
  { name: 'Leta', module: 4, teaches: ['pwas', 'node', 'recursion'] },
  { name: 'Travis', module: 1, teaches: ['javascript', 'html', 'css'] },
  { name: 'Louisa', module: 1, teaches: ['javascript', 'html', 'css', 'node', 'pwas'] },
  { name: 'Christie', module: 3, teaches: ['javascript', 'react', 'node'] },
  { name: 'Will', module: 3, teaches: ['javascript', 'redux', 'react', 'oop', 'scope'] }
];

const cohorts = [
  { cohort: 1806, module: 1, studentCount: 30, curriculum: ['html', 'css', 'javascript'] },
  { cohort: 1804, module: 2, studentCount: 21, curriculum: ['javascript', 'css', 'recursion', 'scope', 'oop'] },
  { cohort: 1803, module: 3, studentCount: 20, curriculum: ['react', 'redux', 'html', 'javascript'] },
  { cohort: 1801, module: 4, studentCount: 18, curriculum: ['pwas', 'mobile', 'node', 'javascript', 'css'] }
];

const modulesByCurriculum = cohorts.reduce((a, { module, curriculum }) => {
  curriculum.forEach((currName) => {
    if (!a[currName]) {
      a[currName] = [];
    }
    a[currName].push(module);
  });
  return a;
}, {});
const output = instructors.reduce((a, { name, teaches }) => {
  a[name] = [...new Set(
    teaches.flatMap(currName => modulesByCurriculum[currName])
  )];
  return a;
}, {});
console.log(output);

If you can't use flatMap, you can spread into concat instead:

const instructors = [
  { name: 'Pam', module: 2, teaches: ['scope', 'recursion', 'node'] },
  { name: 'Brittany', module: 2, teaches: ['oop', 'pwas'] },
  { name: 'Nathaniel', module: 2, teaches: ['oop', 'scope', 'mobile'] },
  { name: 'Robbie', module: 4, teaches: ['node', 'pwas'] },
  { name: 'Leta', module: 4, teaches: ['pwas', 'node', 'recursion'] },
  { name: 'Travis', module: 1, teaches: ['javascript', 'html', 'css'] },
  { name: 'Louisa', module: 1, teaches: ['javascript', 'html', 'css', 'node', 'pwas'] },
  { name: 'Christie', module: 3, teaches: ['javascript', 'react', 'node'] },
  { name: 'Will', module: 3, teaches: ['javascript', 'redux', 'react', 'oop', 'scope'] }
];

const cohorts = [
  { cohort: 1806, module: 1, studentCount: 30, curriculum: ['html', 'css', 'javascript'] },
  { cohort: 1804, module: 2, studentCount: 21, curriculum: ['javascript', 'css', 'recursion', 'scope', 'oop'] },
  { cohort: 1803, module: 3, studentCount: 20, curriculum: ['react', 'redux', 'html', 'javascript'] },
  { cohort: 1801, module: 4, studentCount: 18, curriculum: ['pwas', 'mobile', 'node', 'javascript', 'css'] }
];

const modulesByCurriculum = cohorts.reduce((a, { module, curriculum }) => {
  curriculum.forEach((currName) => {
    if (!a[currName]) {
      a[currName] = [];
    }
    a[currName].push(module);
  });
  return a;
}, {});
const output = instructors.reduce((a, { name, teaches }) => {
  a[name] = [...new Set(
    [].concat(...teaches.map(currName => modulesByCurriculum[currName]))
  )];
  return a;
}, {});
console.log(output);

Upvotes: 2

Related Questions