Search code examples
javascriptarraysfilterreturn

How to .filter an array against an array with .includes?


I've looked at a number of other posts and can't resolve my case.

I am working on a music/chord playing program and I want to filter out all chords (aka objects) that include one or more notes (numbers in my program) that are out of key.

I have an array named chordLibrary filled with objects (e.g., {notesInChord: [5, 8], chordName: 'Major'}). I have another array with numbers (outOfKeyNotes = [11, 12];). I want to .filter and return only the objects in chordLibrary that do not include the numbers in outOfKeyNotes in the element notesInChord.

For example:

// THIS is the original array:
const chordLibrary = [ 
    { notesInChord: [5, 8], chordName: 'Major' },
    { notesInChord: [5, 8, 11], chordName: 'Dominant 7th' },
    { notesInChord: [4, 8, 12], chordName: 'Minor Major 7th' }
];

// THIS is what I hope to end up with after filtering for the array [11,12]:
let chordsInKey = [ 
    { notesInChord: [5, 8], chordName: 'Major' },
];

Here is my program which is currently not working. it simply returns the whole original array.

const chordLibrary = [ 
    { notesInChord: [5, 8], chordName: 'Major' },
    { notesInChord: [5, 8, 11], chordName: 'Dominant 7th' },
    { notesInChord: [4, 8, 12], chordName: 'Minor Major 7th' }
];

let outOfKeyNotes = [11, 12];

console.log(chordLibrary.length);

let chordsInKey = chordLibrary.filter(function(item) {
    return !outOfKeyNotes.includes(item.notesInChord);
});

console.log(chordsInKey);
console.log(chordsInKey.length);

If I change the program so that chordLibrary is simply an array of number values instead of an array of objects, it works fine. It just doesn't suit my needs. Here is a working example of that:

let chordLibrary = [1,2,3,11,12];
let outOfKeyNotes = [11, 12];

console.log(chordLibrary.length);

let chordsInKey = chordLibrary.filter(function(item) {
    return !outOfKeyNotes.includes(item);
});

console.log(chordsInKey);
console.log(chordsInKey.length);

What am I missing? Thanks


Solution

  • You're trying to use includes to see if an array of values includes another array of values.

    Instead, you can use Array.every in your filtering mechanism, which makes sure every element in an array passes a specific test.

    I would change

    return !outOfKeyNotes.includes(item.notesInChord);
    

    to

    return item.notesInChord.every(note => !outOfKeyNotes.includes(note));