简体   繁体   中英

Find the longest word in a string in JS using this code?

Please let me know what is wrong with this code:

I know there are much simpler ways to achieve the desired result, however I want to understand how to make this specific code run, and what are my errors. Try to change as little as possible about it, or else let me know why this could not work. Also note that I am trying to console.log 3 values, not just one. Thank you.

EDIT: Here's the freeCodeCamp exercise against which I'm actually testing if the code works: https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/find-the-longest-word-in-a-string For some reason most answers work in the snippet in here, but not in the freeCodeCamp exercise console?

 function findLongestWordLength(str) { let arr = []; let longestWord = ""; let longestNum = 0; /*If there is a character at str[i] add it to the arr, else if there is whitespace don't add it to the arr. Instead, find the arr.length, if is greater than the previous overwrite longestNum, longestWord and empty the arr, if not just empty the arr and keep going*/ for (let i = 0; i <= str.length - 1; i++) { if (/./i.test(str[i])) { arr.push(str[i]); } else if (/\s/.test(str[i])) { if (arr.length - 1 >= longestNum) { longestNum = arr.length - 1; longestWord = arr.join(""); arr = []; } else { longestNum = longestNum; longestWord = longestWord; arr = []; } } } console.log(arr); console.log(longestWord); console.log(longestNum); return longestNum; } findLongestWordLength("The quick brown fox jumped over the lazy dog");

I'm assuming that with /./i.test(str[i]) you're trying to match everything except spaces. . matches everything except newline characters so I switched it to [^\s] which actually matches everything except spaces. I also took the console logs outside of the loop so the output is somewhat readable.

function findLongestWordLength(str) {

  let arr = [];
  let longestWord = "";
  let longestNum = 0;

  for (let i = 0; i <= str.length - 1; i++) {
    if (/[^\s]/i.test(str[i])) {
      arr.push(str[i]);
    } else if (/[\s]/i.test(str[i])) {
      if (arr.length > longestNum) {
        longestNum = arr.length;
        longestWord = arr.join("");
        arr = [];
      } else {
        longestNum = longestNum;
        longestWord = longestWord;
        arr = [];
      }
    }

  }
  console.log(arr); // last word since you reset arr every step
  console.log(longestWord);
  console.log(longestNum);
  return longestNum;
}

findLongestWordLength("The quick brown fox jumped over the lazy dog");

A better way to do this would be:

function findLongestWordLength(sentence) {
  const words = sentence.split(' ');
  return words.reduce((max, currentWord) => max > currentWord.length ? max : currentWord.length, 0);
}

With the least modifications you would need to make these changes:

  • Ensure that the length of the last word is also verified. Currently it isn't. For that you can just add a space to the input string before doing the loop.
  • Change the test /./i , since that will match anything except a line break. You'll want to check for letters and probably also digits and maybe underscore, but not punctuation. So /\w/ would be an improvement. You can think of even better regexes. Browsers are slowly getting support for /\p{L}/u , which matches letters in any alphabet.
  • The test in the else should be removed, since you just want to deal with any other case here, unconditionally. For instance, a comma will also delimit the word, and there might not be a space following it before the next word starts.
  • Don't subtract one from the array length: it really has the characters of the word (only), so you need the full length.

These are the minimal changes to make it correct:

 function findLongestWordLength(str) { let arr = []; let longestWord = ""; let longestNum = 0; str += " "; // trick to ensure that the last word is also inspected for (let i = 0; i <= str.length - 1; i++) { if (/\w/i.test(str[i])) { // match alphanumerical character, not anything. // The `i` suffix doesn't harm, but is useless here arr.push(str[i]); } else { // Remove any condition here. if (arr.length >= longestNum) { // you need the full length, not minus 1 longestNum = arr.length; // (idem) longestWord = arr.join(""); arr = []; } else { longestNum = longestNum; // not needed longestWord = longestWord; // not needed arr = []; } } //console.log(arr); //console.log(longestWord); //console.log(longestNum); } return longestNum; } console.log( findLongestWordLength("The quick brown fox jumped over the lazy dog") )

As you know there are shorter ways to do this, for instance with this functional programming solution:

 function findLongestWordLength(str) { return Math.max(...str.match(/\w+|$/g).map(s => s.length)); } console.log(findLongestWordLength("The quick brown fox jumped over the lazy dog"));

You need to add items as long as the character is not a space ( /\S/ - uppercase S). If it's a space, you need to to compare the length to the previous longestWord.length , and assign the word to longestWord . In the case of space, you init arr .

Note: the assignments longestNum = longestNum; longestWord = longestWord; longestNum = longestNum; longestWord = longestWord; are redundant, they're already equal to themselves. In addition the longestNum is also redundant, since it's derived from longestWord ( longestWord.length ).

 function findLongestWordLength(str) { let arr = []; let longestWord = ""; for (let i = 0; i < str.length; i++) { if (/\S/.test(str[i])) { // as long as it's not a space arr.push(str[i]); } else { if (arr.length > longestWord.length) { longestWord = arr.join(""); } arr = []; } } return longestWord.length; } var result = findLongestWordLength("The quick brown fox jumped over the lazy dog"); console.log(result);

You can leave out the else if(..) condition if you use a slightly different regex in the first test: /\w/ , looking for any character that can occur in a word.

 function findLongestWordLength(str) { let arr = [], longestWord = "", longestNum = 0; for (let i = 0; i <= str.length - 1; i++) { if (/\w/.test(str[i])) { arr.push(str[i]); } else { if (arr.length - 1 >= longestNum) { longestNum = arr.length - 1; longestWord = arr.join(""); arr = []; } else { longestNum = longestNum; longestWord = longestWord; arr = []; } } } console.log(arr); console.log(longestWord); console.log(longestNum); return longestNum; } var str="The quick brown fox jumped over the lazy dog"; findLongestWordLength(str); // alternatively you could simply do: console.log(str.split(/\s/).sort((a,b)=>b.length-a.length)[0])

The contents of arr will of course be last tested word, in this case "dog". There are two strings of length 5, only the first is found.

As you can see in my snippet, a shorter way of doing it would be:

var longestWord=str.split(/\s/).sort((a,b)=>b.length-a.length)[0]

I would refer to the above excellent answers for restructuring and redundancy, but would also add (since OP wants explanations) that most if not all of the regex/split methods employed here will either push words and include leading/trailing punctuation, or split words mistakenly.

Using \w splits by hyphens and single quotes, which could produce misleading results, depending on what you need.

For example "hello...?" has a longer length than "longest", counting all punctuation. Also "You're" is one word, not two, hence splitting by spaces or relying only on \w is problematic.

When splitting text content into words one should (if word processing, I guess this is a homework question) not only rely on spaces. I use this regex in a current, not yet published project: /[\s.,:;??_<>{}()[\]"`´^$°§½¼³%&¬+=*~#|/\\]/

The above regex allows for hyphenated words which, while technically multiple words joined together, are often read/treated as a single word, ie when creating a janky-type-compund-noun as I just now did.

Finally, language matters. Splitting text content using the above regex works pretty well for English, and doesn't split words by single quote chars, because then we would split "you're a liar!" into ["you", "re", "a", "liar"] , so you'd still need to either clean the resulting array of words of surrounding single quotes (again, could be multiple, perhaps user wrote "'Good evening.'''" by mistake).

Summary: a fundamental part of doing NLP (natural language processing) should nearly always involve a "text cleaning" step and relying on a space or the built in \w special char, even just when processing English text, won't cut it.

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