# Test for an array being subset of another master array

I was trying to build a small utility function to check if an array is part of other array. It's testing if an array is a subset of another master array.

const masterArray = [1,2,3,4,5,6];
const candidateArray = [2,5,6];

//Test for subset.

//create a set from the two.
const s1 = new Set(masterArray.concat(candidateArray));

//Compare the sizes of the master array and the created set
//If the sizes are same, no new elements are added that means
//the candidate is complete subset.
s1.size === masterArray.length;


Can this be handled in a better way?

• Wouldn't that fail if masterArray has duplicate elements? – Martin R Jul 16 '18 at 7:15
• Good point. In my case the master array is always unique. – Sol Jul 16 '18 at 7:22
• I can enhance it by comparing with a new set created from master array (new Set(masterArray)).size – Sol Jul 16 '18 at 8:46
• I am looking for a way to do this with the type system (to check at compile time), if anyone knows how – Alexander Mills Jul 20 '19 at 22:48

So the key here is that I value code that's obvious to others.

Someone else is likely to try to stuff duplicate elements in unless it requires a type refactor; making const masterSet: Set<number> and using that throughout the code is a Good Idea. That "someone else" can often be you two months down the line, too.

In this case I would not say that the point of this length comparison is obvious; it will work but it takes some thinking -- that is why it has bugs with duplicate elements. In this case I would write something which I find more straightforward like,

function isSubsetOf<x>(sub: Iterable<x>, sup: Set<x>): boolean {
for (const x of sub) {
if (!sup.has(x)) {
return false;
}
}
return true;
}


I am also hinting through the type system how this function works by insisting that the subset is any iterable -- so I must be iterating through it.

With a restriction to an array and a set, one can get a little swankier by using the reduce function,

function isSubsetOf<x>(sub: Array<x>, sup: Set<x>): boolean {
return sub.reduce((acc, x) => acc && sup.has(x), true);
}


but probably not all other readers will find that as intuitive as I do, and the former has slightly better runtime characteristics on very large lists that are obviously not subsets.