Home > Blockchain >  Why isn't this constraint in my code causing a specific value to be returned, even though the d
Why isn't this constraint in my code causing a specific value to be returned, even though the d

Time:09-08

I am running through some practice problems on CodeWars right now and have stumbled upon an issue that I cannot seem to figure out. The problem is straightforward and simple enough:

My function should take a string input, and return the first character that is not repeated anywhere in the string.

For example, if given the input 'stress', the function should return 't', since the letter t only occurs once in the string, and occurs first in the string.

As an added challenge, upper- and lowercase letters are considered the same character, but the function should return the correct case for the initial letter. For example, the input 'sTreSS' should return 'T'.

If a string contains all repeating characters, it should return an empty string ("").

My code is as follows:

const firstNonRepeatingLetter = (string) => {
const letters = {};

// Object that I am assigning key/value pairs to based on the number of occurrences of each letter

string.split('')
      .forEach(letter => {
            letter = letter.toLowerCase();
            if (letters[letter] !== undefined) letters[letter]  ;
            if (letters[letter] === undefined) letters[letter] = 1;
        });

for (let key in letters) {
    let val = letters[key];

    // Iterate through object and upon finding the first value of 1, evaluate the casing of the key

    if (val === 1) {
        string.split('')
              .forEach(letter => {
                // *line16* If the letter in the string is the same as the corresponding key in uppercase, return letter
                if (key.toUpperCase() === letter) return letter;
        });
        // Otherwise, return the key as is
        return key;
    };
};

   return '';
};

This passes all tests except for the 'sTreSS' test. I have ran through the process with the debugger, and ironically, the *if conditional on line 16 displays a local Return value: 'T' when reaching this point. However, the forEach continues to iterate and I end up with a return value of 't', which is the next return statement in my block.

I am confounded by this and would appreciate any insight into what is causing the issue.

CodePudding user response:

You could instead use Array.find.

if (val === 1) {
  const findIt = string.split('').find(letter => key.toUpperCase() === letter);
  return findIt || key;  // if findIt is undefined (not found), return key
};

CodePudding user response:

As mdn says:

There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.

Early termination may be accomplished with:

  • A simple for loop
  • A for...of / for...in loops
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()

Array methods: every(), some(), find(), and findIndex() test the array elements with a predicate returning a truthy value to determine if further iteration is required.

As an alternative, you can use findIndex:

const findIndex = string.split('').findIndex(letter => key.toUpperCase() === letter);
return findIndex != -1 
  ?  string.split[findIndex ]
  || key;

But find() is neater :)

  • Related