Count repeated letters in a string
I am stuck with the following problem: I need to find duplicate characters in a string. Basically what I want is a regex that will match like this
hello - ["ll"];
here - ["ee"];
happiness - ["pp","ss"];
pupil - ["pp"];
I have one that matches sequentially repeated characters
/([a-z])\1+/g
Also one that will match repeating characters and everything in between, like this one
/([a-z])(?:.*)\1+/g
But I cannot determine the correct one.
source to share
you can use
([a-zA-Z]).*(\1)
Since you figured out that you are looking for a solution that handles something other than double letters in a string, you should use a non-regular approach like:
Construct an associative array with a count of characters per string:
var obj={}
var repeats=[];
str='banana'
for(x = 0, length = str.length; x < length; x++) {
var l = str.charAt(x)
obj[l] = (isNaN(obj[l]) ? 1 : obj[l] + 1);
}
console.log(obj)
Printing
{ b: 1, a: 3, n: 2 }
Then create an array of your specs:
for (var key in obj) {
if (obj.hasOwnProperty(key) && obj[key]>1) {
repeats.push(new Array( obj[key]+ 1 ).join( key ));
}
}
console.log(repeats)
Printing
[ 'aaa', 'nn' ]
source to share
var obj = {};
var str = "this is my string";
for (var i = 97; i < 97 + 26; i++)
obj[String.fromCharCode(i)] = 0;
for (var i = 0; i < str.length; i++) {
obj[str.charAt(i).toLowerCase()]++;
}
From there, you can tell obj["a"]
to get the number of occurrences for any particular letter.
source to share
For your scenario, the second solution seems to be better. You can get the second letter of another capture group
The Regex you will be (this is your second RegEx with more than one capture group):
/([a-z])(?:.*)(\1)+/g
var re = /([a-z])(?:.*)(\1)+/g;
var str = ['hello', 'here', 'happiness', 'pupil'];
var m;
var result = new Array();
for(var i = 0; i < str.length; i++) {
result[i] = str[i] + "->";
while ((m = re.exec(str[i])) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
result[i] += m[1];
result[i] += m[2] + ",";
}
}
document.getElementById("results").innerHTML = result.join("</br>");
<div id="results"></div>
source to share
More complex than RegExp's solution, however it handles banana
and correctly assassin
where there are two overlapping character groups.
This uses array.map , array.filter, and array.reduce , which means this exact solution doesn't support <= IE8, however it can be easily poly-lized.
function findDuplicateCharacters(input) {
// Split the string and count the occurrences of each character
var count = input.split('').reduce(function(countMap, word) {
countMap[word] = ++countMap[word] || 1;
return countMap;
}, {});
// Get the letters that were found, and filter out any that only appear once.
var matches = Object.keys(count)
.filter(function (key) { return (count[key] > 1); })
// Then map it and create a string with the correct length, filled with that letter.
.map(function (key) {
return new Array(count[key] + 1).join(key);
});
return matches;
}
var results = ['hello', 'here', 'happiness', 'pupil', 'banana'].map(findDuplicateCharacters);
document.getElementById("results").innerHTML = results.join('<br />');
<div id="results"></div>
source to share
var re = /([a-z])(?:.*)(\1)+/g;
var str = ['aaaccbcdd'];
var m;
var result = new Array();
for(var i = 0; i < str.length; i++) {
result[i] = str[i] + "->";
while ((m = re.exec(str[i])) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
result[i] += m[1];
result[i] += m[2] + ",";
}
}
document.getElementById("results").innerHTML = result.join("</br>");
<div id="results"></div>
source to share