Reputation: 1244
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
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
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
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
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
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