-1

I searched over the title and found some solutions, but none of them worked for me. I want something like following:

checkRepeat('ccc','cc');  // should give output 2
checkRepeat('cccaacddcccc','cc');  // should give output 5

and so on. Please help me with this.

What I've tried:

function checkRepeat(string, search) {
    if (!search.length) return 0;
    var pattern = new RegExp('(' + search + ')', 'ig'),
        match = string.match(pattern),
        parts = string.split(pattern).slice().filter(function (i) {
            return i.length;
        });
    console.log(match.length);
    console.log(parts.length - 1);
}
The System Restart
  • 2,873
  • 19
  • 28
  • 6
    and where's the code that shows [what you've tried](http://mattgemmell.com/what-have-you-tried/)? – zzzzBov Nov 24 '14 at 16:36
  • It seems to be that `checkRepeat('cccaacddcccc', '')` should return 13, since it "occurs" in between each letter. By the way, it's highly unlikely regexp is going to work for this, since you're looking for matches which are overlapping. Your solution is not working how? @Begueradj Downvotes are not unreasonable for "gimme-some-code" questions, not matter what the rep is. –  Nov 24 '14 at 16:38
  • 3
    @Begueradj Up/down voting should have nothing to do with one's reputation, but should reflect the quality of the question. – Etheryte Nov 24 '14 at 16:42
  • Correction: you can use regexp, by resetting 'lastIndex' See the duplicate question. –  Nov 24 '14 at 16:43
  • 1
    There's also an answer here which addresses the overlapping case: http://stackoverflow.com/questions/4009756/how-to-count-string-occurrence-in-string. –  Nov 24 '14 at 16:44

3 Answers3

2

Recursion could suit your needs:

// from http://stackoverflow.com/a/646643/1225328
function startWith(str, sub) {
    return str.slice(0, sub.length) === sub;
}

function checkRepeat(str, sub) {
    // stop recursion when "str" or "sub" is empty
    if (!sub.length || !str.length) {
        return 0;
    }
    // recursion on "str" minus its first char
    return (startWith(str, sub) ? 1 : 0) + checkRepeat(str.slice(1), sub);
}

An iterative solution:

function checkRepeat(str, sub) {
    if (!sub.length) {
        return 0;
    }
    var n = sub.length;
    var count = 0;
    for (var i = 0; i <= str.length - n; i++) {
        if (str.slice(i, i + n) === sub) {
            count++;
        }
    }
    return count;
}
sp00m
  • 47,968
  • 31
  • 142
  • 252
  • This would be much more reasonable as a simple loop, not as a recursive method. – Etheryte Nov 24 '14 at 16:48
  • Some have said that the optimal implementation of `startWith` is `str.indexOf(sub) === 0`. Also, if you want to confuse people, you could remove the `? ` : 0`, since boolean values cast when added. –  Nov 24 '14 at 16:48
  • 1
    Note that while this solution is quite elegant, it's also pretty slow and may blow up your stack for very long strings. – helpermethod Nov 24 '14 at 16:49
  • Well, that's not what I read, see http://stackoverflow.com/a/646643/1225328. Who said that? And I have to admit that I'm not trying to confuse people :) – sp00m Nov 24 '14 at 16:51
  • Sorry, I meant to say `str.lastIndexOf(sub, 0) === 0`, which BTW is the polyfill given by MDN. –  Nov 24 '14 at 16:55
  • @sp00m Thanks Sir. just one thing to know, i want to supply a flag as third parameter, depending on that `checkRepeat( 'aaa', 'aa', true)` will return `1` not `2`. – The System Restart Nov 24 '14 at 17:00
1

This should do it with a regex:

function checkRepeat(string, search) {
    if (!search.length) return 0; 
    var myRe = new RegExp(search, 'g');
    var count = 0;
    while (myRe.exec(string) !== null) {
        count++;
        myRe.lastIndex -= search.length-1;
    }
    return count;
}
alert(checkRepeat('ccc', 'cc')); // 2
alert(checkRepeat('cccaacddcccc', 'cc')); // 5

JSFiddle.

Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
kjokinen
  • 101
  • 1
  • 1
  • 6
1

Try this:

function checkRepeat(f, s, o) {
    return (f.length && s.length) 
           ? f.match(new RegExp((o || (undefined === o)) ? '(?=(' + s + '))' : f, 'g')).length 
           : 0;
}

This solution combine your question and also this comment.

checkRepeat('cccaacddcccc','cc');  // output 5
checkRepeat('cccaacddcccc','cc', false);  // output 1, as overlap is set to false
Community
  • 1
  • 1
thecodeparadox
  • 86,271
  • 21
  • 138
  • 164