Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort object by skills

Tags:

javascript

So I found a problem in an article (can't find the link or I'd have the solution) that asked the following question.

Given some user data sort users by skill. The following is the data

const namesAndSkills = {
   // Dev : Skills
   mark : ["javascript","react","java"],
   rob : "javascript",
   patrick : ["javascript", "react", "python"]
 } 

Solution(expected output):

  Javascript: ["mark", "rob", "patrick"],
  react: ["mark", "patrick"],
  java: mark,
  python: patrick

My solution has only been able to separate the skills from the users, but I can't seem to find a way to compare the users with the skills.

const data = {
  // // Dev : Skills
  mark: ["javascript", "react", "java"],
  rob: "javascript",
  patrick: ["javascript", "react", "python"]
}

function swapNamesAndSkills(object) {
  let data = Object.entries(object); //Was thinking of using the separated entries to compare, but couldn't evaluate correctly.

  //Create a map to store our end key / values
  let skillsToNames = new Map();
  let skills = [].concat(...Object.values(object));
  for (let i = 0; i < skills.length; i++) {
    //if map doesnt have the skill as a key, add skill
    if (!skillsToNames.has(skills[i])) {
      //array of names that have the skill
      skillsToNames.set(skills[i], []);
    }
  }
  console.log(skillsToNames);
}
swapNamesAndSkills(data);

As you see I was looking at ways forward, but can't seem to land a solid way to reverse the data. Solution doesn't have to solve the problem, I'm just stuck and can't find my way to the finish line.

like image 281
Robster Avatar asked Jan 25 '26 03:01

Robster


1 Answers

You could reduce through the entries of the object and create a new object. Since value can either be a string or an array, you can use [].concat(value) to get an array of skills to loop through.

Same logic applies while adding a skill as a key to the accumulator. If the skill doesn't exist, just assign acc[skill] = name. If the key already exists, use [].concat(acc[skill], name) because acc[skill] could either be a string or an array.

const namesAndSkills = {
  mark: ["javascript", "react", "java"],
  rob: "javascript",
  patrick: ["javascript", "react", "python"]
}

const output = Object.entries(namesAndSkills).reduce((acc, [name, value]) => {
  [].concat(value).forEach(skill => {
    if (acc[skill])
      acc[skill] = [].concat(acc[skill], name)
    else
      acc[skill] = name;
  })
  return acc
}, {})

console.log(output)

You could also use for...in to loop through the keys of namesAndSkills and create the output

const namesAndSkills = {
  mark: ["javascript", "react", "java"],
  rob: "javascript",
  patrick: ["javascript", "react", "python"]
}

const output = {}

for (const name in namesAndSkills) {
  for (const skill of [].concat(namesAndSkills[name])) {
    if (output[skill])
      output[skill] = [].concat(output[skill], name)
    else
      output[skill] = name;
  }
}

console.log(output)
like image 193
adiga Avatar answered Jan 27 '26 19:01

adiga