11

I'm just a beginner in javaScript and have a background in python. I was trying this exercise to check if every character of the string2 is contained within the string1. For example, if string1 is "hello", I'll return true if string2 is "leh" and false if string2 is "low".

What I came up was this:

function mutation(arr) {
  var set = new Set(string1.split(''));
  for (var i = 0; i < string2.length; i++)
    if (!set.has(string2[i]))
      return false;
  return true;
}

I could also go about converting string2 into a Set and then do take the difference i.e. the operation of set(string2) - set(string1) which will fetch me the set of characters that are in String2 but not in String1 but I read creating a set is costly so I didn't go ahead.

I checked other solutions and everyone was using string1.indexOf(letter) method for checking if every letter in string2 is there in string1 or not.

I want to know when should one use a Set difference. Why everyone is using array.indexOf() method which costs O(n) instead of set.has() method which is O(1). Are there any pitfalls if I'm using set.has(). (say browser compatibility)?

Any recommendation is helpful.

Gass
  • 7,536
  • 3
  • 37
  • 41
Abhinav Srivastava
  • 840
  • 10
  • 17
  • 3
    just curious, how are you determining the the runtimes of set.has() and array.indexOf()? – BenWS Jul 05 '17 at 23:39
  • "*I read creating a set is costly so I didn't go ahead.*" - where did you read that? – Bergi Jul 06 '17 at 02:39
  • 1
    Did you have any look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility or https://kangax.github.io/compat-table/es6/#test-Set? – Bergi Jul 06 '17 at 02:47

3 Answers3

10

You will find more details and browser compatibility on MDN - Set. For implementation of a Set in general, you can read Set - Implementations on Wikipedia.

Implementations described as "general use" typically strive to optimize the element_of, add, and delete operations.

You can also check some test results on the Array vs Set asnwer on Stack Overflow.


To answer your question, although the has operation might be a bit faster than using String's indexOf (or includes), in your specific case the cost of instantiating a new Set for each comparison is much greater.

I created a simple test with the following two methods:

function existsSet(str1, str2) {
  const set = new Set(str1);
  return ![...str2].some(char => !set.has(char));
}

function existsString(str1, str2) {
  return ![...str2].some(char => !str1.includes(char));
}

I called the above methods for 1 million randomly created strings and I got the following results:

existsSet: 1.29s
existsString: 0.47s

That's almost three times slower for the method that instantiates a Set.


You can find the test I run on the following JsFiddle:

https://jsfiddle.net/mspyratos/zwx3zcx1/11/

m.spyratos
  • 3,823
  • 2
  • 31
  • 40
3

In programming, multiple ways lead to the same solution. Using a set with .has() is just as valid as using indexOf(), it all depends on the surrounding code, and the re-use of the objects (eg: sets) you do.

Usually using indexOf() is faster on the CPU and does not care of the special characters (while a traditional simple split implies that words are separated by always the same character).

Building a set cost a little bit more. But it is still pretty fast so it should not be that much of a consideration.

In the end, do what your instinct tells you to do so that your code stays consistent.

Fabien
  • 4,862
  • 2
  • 19
  • 33
1

Let say we have:

const arr = [0,0,1,1]
const mySet = new Set()

mySet.add(arr)

mySet.size returns the number of unique elements in an array. Therefore it can be used to check for duplicate elements by comparing it to the length of the array.

Gass
  • 7,536
  • 3
  • 37
  • 41
amongus
  • 11
  • 1