0

Pretty basic question here I think but not one I could find an answer for - I have a bunch of arrays that I want to extract unique values from. Each array has a list of skills a candidate is proficient in and I want to build an array that lists all skills that have been listed.

This is the code I have which lists a persons name and the skills they have:

const people = [
  { name: "Mike", skills: ["JavaScript", "Java", "Python"] },
  { name: "Bob", skills: ["Python", "Java"] },
];

What I want to do is build an array with each skill listed above only appearing once, no matter how many times its in the arrays above. I have tried using the Set feature as follows:

let options = [...new Set(people)]

but that dosent work for me. Ideally I want the output to be something like:

options["JavaScript", "Java", "Python"]

where each unique value is represented only once. Any help is appreciated.

6 Answers 6

2

Combine all skills to a single array with Array.flatMap(), convert to a Set to get only unique values, and then spread back to an array:

const people = [
  { name: "Mike", skills: ["JavaScript", "Java", "Python"] },
  { name: "Bob", skills: ["Python", "Java"] },
];

const skills = [...new Set(people.flatMap(o => o.skills))];

console.log(skills);

0
0

You should use lodash .

Then, you can use _.difference(array1,array2);

Goodluck !

0

The idea of using a Set is fine, but you need to add the skills to the set, no the entire people objects. One approach to solve this is to traverse every array of skills while add they to the set:

const people = [
  {name: "Mike", skills: ["JavaScript", "Java", "Python"]},
  {name: "Bob", skills: ["Python", "Java"]},
];

let skills = new Set();
people.forEach(p => p.skills.forEach(s => skills.add(s)));
console.log("skills => ", [...skills]);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

0

I would also add a polyfill to this .flatMap(), because this is not supported by IE at all.

if (!Array.prototype.flatMap) {
  Object.defineProperty(Array.prototype, "flatMap", {
    value: function(callback, thisArg) {
      return this.map(callback, thisArg).reduce((a, b) => a.concat(b), []);
    },
    configurable: true,
    writable: true
  });
}

const people = [
  { name: "Mike", skills: ["JavaScript", "Java", "Python"] },
  { name: "Bob", skills: ["Python", "Java"] },
];

const skills = [...new Set(people.flatMap(o => o.skills))];

console.log(skills);

0

To achieve expected result, use below of using reduce and Set

const people = [
  { name: "Mike", skills: ["JavaScript", "Java", "Python"] },
  { name: "Bob", skills: ["Python", "Java"] },
];

console.log(people.reduce((acc, v) => {
   acc.push(...v.skills)
   return [...new Set(acc)]
}, []))

0

Way more verbose than it needs to be, but:

for (let individual of people) {
  for (let skill of individual.skills) {
    options.indexOf(skill) < 0 ? options.push(skill) : '';
  }
}

Could do it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.