简体   繁体   中英

JavaScript “firstNonRepeatingLetter” function returning undefined instead of a character?

Here is the problem statement:

Write a function named firstNonRepeatingLetter† that takes a string input, and returns 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'.

Below is my code, which returns undefined. I'm not able to catch the error.

 function firstNonRepeatingLetter(s) { var x = s.replace(" ", ""); for (var i = 0; i < x.length; i++) { if (x.charCodeAt(i) < 96) { var y = x.replace(x[i], ""); var z = String.fromCharCode(x.charCodeAt(i) + 32); if (y.indexOf(x[0]) > -1 || y.indexOf(z) > -1) { continue; } else { var m = x[i]; } return m; } else if (x.charCodeAt(i) > 96) { var y = x.replace(x[i], ""); var z = String.fromCharCode(x.charCodeAt(i) - 32); if (y.indexOf(x[0]) > -1 || y.indexOf(z) > -1) { continue; } else { var m = x[i]; } return m; } } } 

Your conditions y.indexOf(x[0]) > -1 are incorrect. You don't need to compare the first character, but the i th character. Replace both of them by y.indexOf(x[i]) > -1 .


Some hints:

  • Please avoid single-letter variable names . They make it incredibly hard to debug and understand your code.
  • var declarations inside blocks, like for , if , etc. don't do anything useful. You've redeclared var m twice. This just adds to the confusion.
  • .replace(" ", "") only removes the first space, even though you probably meant to remove all spaces . Either use regexes (also useful to add more cases, or to limit your inputs to specific characters), or use replaceAll (note the browser compatibility and proposal state). Using regexes might look like .replace(/\\s/g, "") to remove all whitespace , or .replace(/[^az]/gi, "") to remove anything that isn't a Latin letter.
  • Instead of adding or subtracting 32 from a charcode, just use .toUpperCase and .toLowerCase .
  • Likewise, comparing charcodes smaller or greater than 96 won't handle the character with this exact charcode, which is the ` character. Instead, consider converting the entire string to either uppercase or lowercase, rather than handling both in two separate cases.
  • Lastly, depending on whether the assignment allows for that, consider using Object and Array methods.

These are two ways how the function can be written in ECMAScript 2015+:

const getFirstUniqueLetter = (string) => {
  string = [...string.replace(/\s/g, "")];

  const {
    map,
    unique
  } = string.reduce((result, character) => {
      result.map[character.toLowerCase()] = (result.map[character.toLowerCase()] || 0) + 1;

      if(!result.unique.includes(character)){
        result.unique.push(character);
      }

      return result;
    }, {
      map: {},
      unique: []
    });

  // You can add the `|| ""` in the next line to get a default output of the empty string, if no character is unique. Otherwise, `undefined` is returned.
  return unique.find((character) => map[character.toLowerCase()] === 1) /* || "" */;
};
const getFirstUniqueLetter = (string) => {
  string = string.replace(/\s/g, "");

  // You can add the `|| ""` in the next line to get a default output of the empty string, if no character is unique. Otherwise, `undefined` is returned.
  return [...string].find((character) => string.match(new RegExp(character, "gi")).length === 1) /* || "" */;
};

This doesn't solve your code as written, but I thought I'd provide an alternative approach.

  function firstNonRepeatingLetter(s){ var allCharacters = s.split(''); var character; var characterMap = {}; //get all character counts for(var i=0;i<allCharacters.length;i++){ character = allCharacters[i]; if(typeof(characterMap[character]) == 'undefined'){ characterMap[character] = 0; } characterMap[character]++; } //remove any duplicates for(var c in characterMap){ if(characterMap[c] > 1){ delete characterMap[c]; } } //find the first character in your string that is *still* in the map for(var i=0;i<allCharacters.length;i++){ character = allCharacters[i]; if(typeof(characterMap[character]) != 'undefined'){ return character; } } //all characters in the string were duplicated (eg "ABBA") return 'No non repeating letters'; } console.log(firstNonRepeatingLetter("stress")); console.log(firstNonRepeatingLetter("doodle")); console.log(firstNonRepeatingLetter("abba")); console.log(firstNonRepeatingLetter("supercalifragilisticexpialidocious")); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM