Human Cyborg Relations
Human Cyborg Relations

Reputation: 1244

Searching for phrases, loop executed incorrectly

This is an updated version of a previous question, but it requires a different answer.

I'm trying to search for phrases in a string.

var string = "blahmehfoobar hello random stuff here blahblah blegh coding stackover flow computersc ience";

var textToFind = ["blah", "random stuff", "stackover flow comput"];
var counter = 0;

for (var i = 0; i < textToFind.length; i++){
    var text = textToFind[i];
    console.log('finding: ' + text);
    for (var j = 0; j < string.length; j++){
        if (text.charAt(0) === string.charAt(j)){
            console.log(string.substring(j, text.length));
            if (text === string.substring(j, text.length)){
                counter++;
            }
        }
    }
}

console.log(counter);

The counter should be 5 at the end.

The output that I'm getting is weird:

finding: blah
blah
mehfoo
mehfoobar hello random stuff here
mehfoobar hello random stuff here blah
mehfoobar hello random stuff here blahblah
finding: random stuff

r hello
r hello random stuff he
r hello random stuff here blahblah blegh coding stackove
r hello random stuff here blahblah blegh coding stackover flow compute
finding: stackover flow comput
andom
andom stuff here blahblah blegh coding
andom stuff here blahblah blegh coding stackover flow computer

I don't understand why string.substring(j, text.length) is being executed after printing the first found phrase. I've tried debugging this to no avail.

Expected output:

finding: blah
blah
blah
blah
finding: random stuff
random stuff
finding: stackover flow comput
stackover flow comput

Edit: I am NOT looking for an alternative solution. I just want to know why the loop is going wrong and why I'm not getting the expected output

Upvotes: 0

Views: 44

Answers (5)

Tim Consolazio
Tim Consolazio

Reputation: 4888

Anudder one...

var myString = "blahmehfoobar hello random stuff here blahblah blegh coding stackover flow computersc ience";
var textToFind = ["blah", "random stuff", "stackover flow comput", "meh", "foo" ];

let counter = 0;
textToFind.forEach ( ( v, i ) => {
  let sub = myString;
    while ( i !== -1 ) {
      i = sub.indexOf ( v );
      counter += ( i === -1 ? 0 : 1 );
      sub = sub.slice ( i + v.length );
    }
});

Sneaky...by using the iteration val "i" in the forEach, you don't have to init it in the sub loop.

If I get the requirement, this should log "7" (and does).

Upvotes: 0

ibrahim mahrir
ibrahim mahrir

Reputation: 31712

As for why your code is wrong? It's because you're using substring instead of substr.

substr: takes two parameters, an index which will be the anchor from where the substring will begin, and an amount (how many chars).

substring: takes two parameters (two indexes, and return a substring from the first one to the last one).

Upvotes: 1

JorgeObregon
JorgeObregon

Reputation: 3320

Answering your question, see the comment in the snippet below:

var string = "blahmehfoobar hello random stuff here blahblah blegh coding stackover flow computersc ience";

var textToFind = ["blah", "random stuff", "stackover flow comput"];
var counter = 0;

for (var i = 0; i < textToFind.length; i++){
    var text = textToFind[i];
    console.log('finding: ' + text);
    for (var j = 0; j < string.length; j++){
        if (text.charAt(0) === string.charAt(j)){
            console.log(string.substring(j, text.length));
            
            // just replace `if (text === string.substring(j, text.length))`
            //  .......with `if (text === string.substring(j, j+text.length))`
            if (text === string.substring(j, j+text.length)){
                counter++;
            }
        }
    }
}

console.log(counter);

Not answering your question now... ;) Even though you are NOT looking for an alternative solution, there's a simpler way to find the text.

var string = "blahmehfoobar hello random stuff here blahblah blegh coding stackover flow computersc ience";
var textToFind = ["blah", "random stuff", "stackover flow comput"];
var counter = 0, matches = [];

textToFind.map(function(search){
  matches = matches.concat(string.match(new RegExp(search, 'ig')));
});
console.log(matches.length);

Upvotes: 0

Snowmonkey
Snowmonkey

Reputation: 3761

It's a matter of how you're using substring. the start and end values are both zero-index based, not start and length. This will work:

var string = "blahmehfoobar hello random stuff here blahblah blegh coding stackover flow computersc ience";

var textToFind = ["blah", "random stuff", "stackover flow comput"];
var counter = 0;

for (var i = 0; i < textToFind.length; i++){
    var text = textToFind[i];
    console.log('finding: ' + text);
    for (var j = 0; j < string.length; j++){
        if (text.charAt(0) === string.charAt(j)){
          console.log(text.length +" characters: "+string.substring(j, j+text.length) )
    
            if (text == string.substring(j, j+text.length)){
            console.log(text+" found!");
                counter++;
            }
        }
    }
}

console.log(counter);

Note that rather than using text.length as my end point, I'm using j+text.length -- this ensures that I set my endpoint appropriately.

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386746

You could iterate the search array and use indexOf with a start value for searching.

var lotsOfText = "blahmehfoobar hello random stuff here blahblah blegh coding stackover flow computersc ience",
    textToFind = ["blah", "random stuff", "stackover flow comput"];
    counter = textToFind.reduce(function (count, phrase) {
        var pos = lotsOfText.indexOf(phrase);
        while (pos !== -1) {
            count++;
            pos = lotsOfText.indexOf(phrase, pos + 1);
        }
        return count;
    }, 0);

console.log(counter);

Upvotes: 0

Related Questions