0

My goal is to get the result of 3 since in "aaBbCChr" letters a,b and c are repeating themselves. I've made this function, everything looks right, but it just doesn't work properly.

function duplicateCount(text) {
  let lettersArray = text.split("");
  let duplicateResult = 0;

  lettersArray.map(function(letter) {
    let regexLetter = new RegExp(letter, "gi");
    let matchesCount = text.match(regexLetter).length;
    if (matchesCount > 1) {
      duplicateResult + 1;
    } else {};
  });
  return duplicateResult;
};
alert(duplicateCount("aaBbCChr"));
Neia
  • 59
  • 6
  • Is the repetition consecutive? or if 'a' is present anywhere more than once, it counts? – sbsatter May 04 '20 at 13:42
  • What is the output and what do you expect the output to be? – Anger Density May 04 '20 at 13:43
  • Your regex letter gets reinitialized on each iteration. So it would not work in the way you would want it to work. – Utsav Patel May 04 '20 at 13:44
  • `duplicateResult + 1;` <-- yeah, that is not doing anything, hence why it is 0 since you never actually change the variable. Once you fix that typo, your code is going to count each dupe more than once. – epascarello May 04 '20 at 13:46
  • Try this: (str)=> str.toLowerCase().split("").sort().join("").match(/(.)\1+/g).length – Max May 04 '20 at 14:15
  • Thank you, everyone, for your responses. I am a beginner and my coding knowledge is not much, so I didn't understand some things that you guys written in the answers. But now I do understand why my code is not working. Will try to learn each topic one step at a time – Neia May 04 '20 at 16:35
  • @sbsatter yes, the second one, if any letter is present more than once it counts (+1). I looked at your solution, appreciate the minimal changes you've made, but I gotta read and learn some info about ```new Set()``` thing – Neia May 04 '20 at 16:42
  • @Neia A set is a simple data structure, just like the set problems you ever did in math class. A set does not allow duplicate elements, and in your solution, you are counting the duplicate more than once (just because no one is tracking that it has been counted). – sbsatter May 05 '20 at 06:04

4 Answers4

0

Issues with your code:

  1. duplicateResult + 1; This doesn't change the value of duplicateResult. You need to use a statement that actually increases its value like duplicateResult += 1;

  2. lettersArray also contains the letters multiple times. First remove the duplicates there before looking whether they appear multiple times in the string or you will count them multiple times. See Get all unique values in a JavaScript array (remove duplicates)

  3. Make all lowercase letters in lettersArray so that you don't count the same letter twice when it appears in lowercase and uppercase.

This code works

function duplicateCount(text) {
  let lettersArray = text.toLowerCase().split("");
  let duplicateResult = 0;


  function onlyUnique(value, index, self) { 
      return self.indexOf(value) === index;
  }
  lettersArray = lettersArray.filter( onlyUnique ); 

  lettersArray.map(function(letter) {
    let regexLetter = new RegExp(letter, "gi");
    let matchesCount = text.match(regexLetter).length;
    if (matchesCount > 1) {
      duplicateResult += 1;
    } else {};
  });
  return duplicateResult;
};
alert(duplicateCount("aaBbCChr"));

Another approach is to invert the logic used in Get all unique values in a JavaScript array (remove duplicates) to use filter to filter out all those characters that appear multiple times and then count those.

function duplicateCount2(text) {
  let lettersArray = text.toLowerCase().split("");
  let duplicateResult = 0;

  function onlyNonUnique(value, index, self) { 
      return self.indexOf(value) !== index;
  }
  lettersArray = lettersArray.filter(onlyNonUnique); 
  duplicateResult = lettersArray.length;

  return duplicateResult;
};
alert(duplicateCount2("aaBbCChr"));
NineBerry
  • 26,306
  • 3
  • 62
  • 93
0

As mentioned in other comments, your problem is that you're resetting duplicateResult = 1 to a duplicate result. You probably meant to do duplicateResult += 1, but even that is incorrect because you said that you only want to get repeated characters, so no matter how many times a letter repeats, if it repeats at all, you only count it once.

My approach would be to count the characters in the string in an object (key is the letter, value is the occurrence count) and afterwards count the number of keys that have an occurrence count of more than 1.

function duplicateCount(text) {
    const isValidLetter = /[a-z]/i; // a through z, case insensitive

    const charCounts = text.split('').reduce(function(acc, char) {
        if(isValidLetter.test(char)) {
            char = char.toLowerCase();
            if(acc[char] === undefined) {
                acc[char] = 1;
            } else {
                acc[char] += 1;
            }
        }
        return acc;
    }, {});

    return Object.keys(charCounts).filter(c => charCounts[c] > 1).length;
}

alert(duplicateCount('aaBbCChr'));
n8jadams
  • 991
  • 1
  • 9
  • 21
0

It is far easier to do it with changing the structure to an object

 const reduced = [...myChars].reduce((map, charCaseSensitive) => {
   const char = charCaseSensitive.toLowerCase();
   if(map[char]) map[char]++;
   else map[char] = 1;
    return map;
}, {};
const numberOfRepeatedChars = Object.values(reduced).filter(v => v > 1).length;
grzim
  • 534
  • 3
  • 10
0

Here's the version making minimal changes to your code. You need to lowercase the string here so that the same letter in caps is not counted again.

function duplicateCount(text) {
  let lettersArray = text.toLowerCase().split("");
  let duplicateResult = 0;
  let set = new Set();
  lettersArray.map(function(letter) {
    let regexLetter = new RegExp(letter, "gi");
    let matchesCount = text.match(regexLetter).length;
    if (!set.has(letter) && matchesCount > 1) {
      set.add(letter);
      duplicateResult += 1;
    } else {};
  });
  return duplicateResult;
};
alert(duplicateCount("aaBbCChr"));
sbsatter
  • 591
  • 3
  • 22