Javascript find objects that contain matching elements from arrays in another object

78 Views Asked by At

I have two objects:

const people = [
{
    name: "Dave",
    fruit: ["apple", "pear"],
    veg: ["asparagus", "peas"]
},
{
    name: "Frank",
    fruit: ["mango", "banana"],
    veg: ["sweetcorn"]
},
{
    name: "Alice",
    fruit: ["mango", "peach"],
    veg: ["asparagus"]
}];

const demographics = {
  fruit: ["apple", "mango"],
  veg: ["asparagus"]
}

I would like to find which 'people' like the fruit 'apple' or 'mango' and the veg 'asparagus', as defined in the 'demographics' object, like so:

[{
    name: "Dave",
    fruit: ["apple", "pear"],
    veg: ["asparagus", "peas"]
},
{
    name: "Alice",
    fruit: ["mango", "peach"],
    veg: ["asparagus"]
}]

I've been staring at this all day and am not advanced enough to dig into objects like this. Can anyone help? If possible, I would like to use underscore, but not essential.

3

There are 3 best solutions below

0
cmgchess On BEST ANSWER

first I converted the demographics object to an array so i can iterate easily. after that filter the person array with the conditions
check every demographic where in each demographic at least 1 satisfies (is inside the veg or fruit.. arrays of a person).
You can find equivalent methods pairs,filter,some,every,contains if you want to convert above using underscore

const people = [
{
    name: "Dave",
    fruit: ["apple", "pear"],
    veg: ["asparagus", "peas"]
},
{
    name: "Frank",
    fruit: ["mango", "banana"],
    veg: ["sweetcorn"]
},
{
    name: "Alice",
    fruit: ["mango", "peach"],
    veg: ["asparagus"]
}];

const demographics = {
  fruit: ["apple", "mango"],
  veg: ["asparagus"]
}

const demographicsEntries = Object.entries(demographics)

const res = people.filter(person => demographicsEntries.every(([k,v]) => v.some(val => person[k].includes(val))))

console.log(res)

0
Subhadeep On

people in here is an array of objects.

const people = [
{
    name: "Dave",
    fruit: ["apple", "pear"],
    veg: ["asparagus", "peas"]
},
{
    name: "Frank",
    fruit: ["mango", "banana"],
    veg: ["sweetcorn"]
},
{
    name: "Alice",
    fruit: ["mango", "peach"],
    veg: ["asparagus"]
}];

const demographics = {
  fruit: ["apple", "mango"],
  veg: ["asparagus"]
};

people.filter(person =>
    person.fruit.some(fruitName=> demographics.fruit.includes(fruitName)) && person.veg.some(vegName=> demographics.veg.includes(vegName)) && person);

Hope this will help (y)

0
Andy On

Modern JavaScript has a lot of really useful array and object methods that you can use to spare the additional code footprint of Underscore.

In essence (links to documentation below) you want to filter out all of the people who have at least some of the elements in their fruit/veg arrays that appear in every corresponding query array.

const data=[{name:'Dave',fruit:['apple','pear'],veg:['asparagus','peas']},{name:'Frank',fruit:['mango','banana'],veg:['sweetcorn']},{name:'Alice',fruit:['mango','peach'],veg:['asparagus']}];

// Accepts some data, and the query object
function find(data, query) {
  
  // `filter` out all the people...
  return data.filter(person => {
    
    // ...who, for every query key (fruit/vegetable),
    // have at least one item in their fruit/veg array
    // that includes an item in the corresponding query array
    return Object.keys(query).every(key => {
      return query[key].some(el => {
        return person[key].includes(el);
      });
    });
  });
}

const query={fruit:['apple','mango'],veg:['asparagus']};
console.log(find(data, query));

const query2={fruit:['apple'],veg:['peas']};
console.log(find(data, query2));

const query3={fruit:['banana'],veg:['peas']};
console.log(find(data, query3));

Additional documentation