2

I am trying to compare two strings to see if ALL of one of the string's input is also within another string, regardless of order.

So far I have the following code...

What am I doing wrong?

var str1= "rkqodlw"
var str2= "world"

StringScrambler(str1, str2);

function StringScrambler(str1, str2) {
    var string1= str1.split("").sort();
        console.log(string1);
    var string2 = str2.split("").sort();
        console.log(string2);
    matches = [];
    for (i=0; i< string1.length; i++) {
        for (j=0; j<string2.length; i++) {
            while (j === i) {
              matches.push(j);
              console.log(matches);
              var matchSort = matches.sort();
              console.log(matchSort);
                if (matchSort === string2) {
                    return true;
                }else {
                    return false;
                }
            }
        }
    }
}
Crystal
  • 1,425
  • 1
  • 22
  • 34
  • you can't compare array with `===` , why use a `while` loop ? I guess you forget to check for duplicate letters. – Hacketo Jul 28 '15 at 07:48

7 Answers7

1

var one = "dlrow";
var two = "world";
var allCharsFound = true;
one.split("").map(function(char) {
    if (two.indexOf(char) < 0) {
        allCharsFound = false;
    }
});
console.log(allCharsFound);
Lord Midi
  • 754
  • 1
  • 9
  • 25
1
var str1= "rkqodlw";
var str2= "world";

function test($str1, $str2) {
  var string2 = str2.split("");
  for(var i=0; i<string2.length; i++) {
    if (str1.indexOf(string2[i]) == -1) {
      return false;
    }
  }
  return true;
}
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Taff
  • 231
  • 1
  • 13
1

All the answers this far work fine but they will not work for words with double letters in the second string but not in the first (for eg. 'worlld' - notice the double L). The trick is to affect the first word such that it removes the found character(s) so that the same letter is not checked again. Something like this would do the trick:

// Check if the second string's characters are
// found in the first string
function StringScrambler(str1, str2) {
  var arr1 = str1.split(''),
      arr2 = str2.split(''),
      isATrueSubset = true,
      indexOfChar;

  arr2.forEach(function(char) {
    indexOfChar = arr1.indexOf(char);
    if (indexOfChar > -1) {
      // Remove the character that was found
      // to avoid matching against it again
      arr1.splice(indexOfChar, 1);
    } else {
      isATrueSubset = false;
      // No need to continue
      return;
    }
  });

  console.log(isATrueSubset);
  return isATrueSubset;
}

StringScrambler('rkqodlw ', 'world '); // outputs true
StringScrambler('rkqodlw ', 'worlld '); // outputs false
walmik
  • 1,440
  • 2
  • 13
  • 30
  • Would have answered but you hit the nail on the head here - my preferred way of doing it would probably be to sort both of the strings rather than splitting into an actual array, then treat them like arrays and iterate through, as soon as you hit the end of search string then it's found, but if you hit the end of the source string then it isn't... – Rycochet Jul 28 '15 at 08:27
  • Thanks for your comment Rycochet! The reason I didn't go for a sort is I feel it wouldn't matter as the order of the letters is not something the questioner is concerned about. I d ve liked to splice it at string level as well but JS doesn't have a built-in splice for String like it has for Array. Anyway, this was a fun little question & I m sure you came close to solving it too :) – walmik Jul 28 '15 at 08:34
  • Please note that not all browsers support foreach without a polyfill – mplungjan Jul 28 '15 at 09:44
  • Splice is an expensive operation - so if both strings are sorted then simply looking at the next character in turn means you can say "oh, this doesn't match" really quickly and without much extra memory or cpu overhead. It's not much of a difference really - and treating the string as an array is more memory efficient on mobile devices with their poor garbage collection ;-) – Rycochet Jul 28 '15 at 11:09
0

If str2 is always a subset of str1, then this answer can be used

Compute intersection of two arrays in JavaScript

var arr1 = "rkqodlw".split("");
var arr2 = "world".split("");

var commonValues = arr2.filter(function(value) { 
  return arr1.indexOf(value) > -1; 
});

alert(commonValues.join(""))
Community
  • 1
  • 1
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

You can use the following code to do this task:

alert (AllFirstInSecond("world", "rkqodlw"));
alert (AllFirstInSecond("worldz", "rkqodlw"));

function AllFirstInSecond(str1, str2) {
    var pos = str1.length - 1;
    while (pos >= 0) {
        if (str2.indexOf(str1.substr(pos--,1)) == -1) {
            return false;
        }
    }
    return true;
}

It simply checks every single character in the first string to see if it's in the second. If not, it returns false.

Only once all have been found does it return true.

There are possibilities for optimisation (every character is checked even if it's a duplicate that's already been checked) but, unless your strings are particularly large, there's probably not much absolute gain to be had.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

This will compare each words of the second string in the first one and if its present it will be added in the mathes array.

var str1= "rkqodlw";
var str2= "world2";

StringScrambler(str1, str2);

function StringScrambler(str1, str2) {

var string2 = str2.split("").sort();

console.log(string2);
matches = [];
for (j=0; j<string2.length; j++) {
    if(str1.indexOf(string2[j]) > -1){
         matches.push(string2[j]);
        console.log(string2[j]);    
    }
}
console.log(matches);

}
robin
  • 1,893
  • 1
  • 18
  • 38
0

try this:

var str1= "rkqodlw"
var str2= "world"

StringScrambler(str1, str2);

  function StringScrambler(str1, str2) {
  var string1 = str1.split("").sort();

  var string2 = str2.split("").sort();

  matches = [];
   for (i = 0; i < string1.length; i++) {
      if (string2.indexOf(string1[i]) > -1) matches.push(string1[i]);
   }
return matches
}
maioman
  • 18,154
  • 4
  • 36
  • 42