-1

I have two arrays:

const issues  = [{ id: 'foo', state: { label: 'bar'} }]
const states  = [{ label: 'bar' }, { label: 'baz' }]

How do I filter the issue array for objects which contain state from the states array?

I have the following but it doesn't work

return issues.filter(issue => {
        return states.includes(issue.state)
 })

bear
  • 11,364
  • 26
  • 77
  • 129

2 Answers2

1

If all your values in the state are JSON stringifiable, such as strings, booleans, numbers, null, and arrays/objects that only contain JSON stringifiable values, then a fast approach exists with a set of JSON:

const issues = [{ id: 'foo', state: { label: 'bar'} }]
const states = [{ label: 'bar' }, { label: 'baz' }]

const stateSet = new Set(states.map(state => JSON.stringify(state)))

const filtered = issues.filter(issue => stateSet.has(JSON.stringify(issue.state)))

If you you can't stringify to JSON, then copy the deepCompare function from this answer, and use that with some:

const issues = [{ id: 'foo', state: { label: 'bar'} }]
const states = [{ label: 'bar' }, { label: 'baz' }]

function deepCompare() {
    // ...
}

const filtered = issues.filter(issue => states.some(state => deepCompare(state, issue.state)))
Aplet123
  • 33,825
  • 1
  • 29
  • 55
1

Two objects with the same keys are still different objects in memory, and therefore using the equality or identity comparison operators between them simply won't work. One way to do this fairly robustly is to check that all the key/value pairs between each object are the same. I created a function to do this.

const issues  = [{ id: 'foo', state: { label: 'bar'} }]
const states  = [{ label: 'bar' }, { label: 'baz' }]

function objectsMatch(obj1, obj2) {
  const entries1 = Object.entries(obj1);
  const entries2 = Object.entries(obj2);
  if (entries1.length !== entries2.length) {
    return false;
  }
  return entries1.every(([key, value]) => {
    return obj2[key] === value;
  });
}

const matching = issues.filter(issue => {
  return states.some(state => objectsMatch(state, issue.state));
});

console.log(matching);

Note that you could also use JSON.stringify, but this is problematic because complex objects like functions can't be represented in JSON, and you might get some false positives!

Nick
  • 16,066
  • 3
  • 16
  • 32