Omar
Omar

Reputation: 3040

Need to match object values from one array to the object values from another array

In the following code. I am trying to get the id of a variant that matches the selected objects

const selected = [ { "id": 14 }, { "id": 95 } ]

const variants = [
  {
    "id": 1,
    "option_values": [ { "id": 7 }, { "id": 95, } ]
  },
  {
    "id": 2,
    "option_values": [ { "id": 8 }, { "id": 95, } ]
  },
  {
    "id": 3,
    "option_values": [ { "id": 14 }, { "id": 95, } ]
  }
]

function filterVaiant() {
    return variants.filter( options => {
        // return id 3 because it matches the selected objects
    });
}

console.log(filterVaiant());

The filter function should return variant id:3 because it has the same option values as the selected option values.

follow up

const colors = require('colors');

const selected = [ { "id": 14 }, { "id": 95 }, { "id": 21 } ]

let selected_ids  = selected.map(e=>e.id);

const variants = [
  {
    "id": 1,
    "option_values": [ { "id": 7 }, { "id": 95, } ]
  },
  {
    "id": 2,
    "option_values": [ { "id": 8 }, { "id": 95, } ]
  },
  {
    "id": 3,
    "option_values": [ { "id": 14 }, { "id": 95, } ]
  },
  {
    "id": 4,
    "option_values": [ { "id": 14 }, { "id": 95, }, { "id": 21 } ]
  }
]

let vID = variants.filter(e=> e.option_values.every(e=> selected_ids.indexOf(e.id) > -1));

console.log("answer:",vID) // Returns 3 and 4 but should only return 4

in this scenario vID is 3 and 4 but should only return 4 because it is the only one that matches the selections exactly.

Upvotes: 2

Views: 431

Answers (4)

Novy
Novy

Reputation: 1518

Another solution with map only indexof and join:

const selected = [ { "id": 14 }, { "id": 95 } ]


const variants = [
  {
    "id": 1,
    "option_values": [ { "id": 7 }, { "id": 95, } ]
  },
  {
    "id": 2,
    "option_values": [ { "id": 8 }, { "id": 95, } ]
  },
  {
    "id": 3,
    "option_values": [ { "id": 14 }, { "id": 95, } ]
  }
]

function filterVaiant(selected) {
    return variants[variants.map(obj => obj.option_values).map(outterarray => outterarray.map(innerArray=>innerArray.id).join('-') ).indexOf(selected.map(eb=>eb.id).join('-'))];
}

console.log(filterVaiant(selected));

Upvotes: 1

charlietfl
charlietfl

Reputation: 171689

Using a Set to store the selected Id's to look up and Array#every in a filter

const selected = [ { "id": 14 }, { "id": 95 } ]

const variants = [
  {
    "id": 1,
    "option_values": [ { "id": 7 }, { "id": 95, } ]
  },
  {
    "id": 2,
    "option_values": [ { "id": 8 }, { "id": 95, } ]
  },
  {
    "id": 3,
    "option_values": [ { "id": 14 }, { "id": 95, } ]
  }
]

function filterVaiant(selected) {
    let ids = new Set(selected.map(({id})=>id))
    return variants.filter( o => o.option_values.every(({id})=>ids.has(id)));
}

console.log(filterVaiant(selected));

Upvotes: 2

Muhammad Usman
Muhammad Usman

Reputation: 10148

You can use .filter and .every to achieve this like

const selected = [ { "id": 14 }, { "id": 95 } ];

var ids  = selected.map(e=>e.id);


const variants = [
  {
    "id": 1,
    "option_values": [ { "id": 7 }, { "id": 95, } ]
  },
  {
    "id": 2,
    "option_values": [ { "id": 8 }, { "id": 95, } ]
  },
  {
    "id": 3,
    "option_values": [ { "id": 14 }, { "id": 95, } ]
  }
];

var o = variants.filter(e=> e.option_values.every(e=> ids.indexOf(e.id) > -1));

console.log(o)

What's happening here is, get all the selected ids in an array, then filter the variants array based on if every entry of option_values has all the entries as the selected ids.

Upvotes: 2

Ori Drori
Ori Drori

Reputation: 192242

For each object, check that all items in selected appear in option_values (ops alias) by checking that the length is equal, and using Array.every(), and Array.find():

const selected = [ { "id": 14 }, { "id": 95 } ]

const variants = [{"id":1,"option_values":[{"id":7},{"id":95}]},{"id":2,"option_values":[{"id":8},{"id":95}]},{"id":3,"option_values":[{"id":14},{"id":95}]}];

function filterVaiant() {
  return variants.filter(({ option_values: ops }) => {
    if (selected.length !== ops.length) return false;
    return selected.every(({ id }) => 
      ops.find((o) => id === o.id));
  });
}

console.log(filterVaiant());

Upvotes: 2

Related Questions