0

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");

4
  • 1
    Maybe move some of the console.logs outside the loop. Also why not split on \s and ignore punctuation? Commented Nov 10, 2019 at 17:22
  • 2
    if (/./i.test(str[i])) { is testing any char, are you looking for a full stop, then you need \. - if you are looking for any alphabetical char you want [a-zA-Z0-9] Commented Nov 10, 2019 at 17:23
  • 2
    What are you expecting this to do? longestNum = longestNum; longestWord = longestWord; Commented Nov 10, 2019 at 17:25
  • Fix your snippet Commented Nov 10, 2019 at 17:38

5 Answers 5

1

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);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I did not understand why: ``` const words = sentence.split(' '); ``` was able to split the sentece in words instead of characters. What am I missing?
1

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"));

3 Comments

Hi. Why the $ (end of string) in the RegExp is needed in this case?
I added it as a way to avoid an exception when you pass a string that has no words at all (like an empty string). In that case match would return null (not an array). So to still get an array, I add $, which matches with the end of the string (zero characters), and so there is an extra match that will always work, and will give a matching string of length 0. There are of course many other ways to deal with this case.
Nice idea to circumvent the annoying null problem. I've learned something :)
1

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; 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);

Comments

0

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]

3 Comments

Thank you, I see this code works correctly in the snippet here but do you have any idea why it doesn't work at all in the freeCodeCamp's console? I make sure to copy it exactly but it's simply not achieving what it should. I also notice this with the other solution I got.
@DimhDoychev, could you edit your question and add a link to the freeCodeCamp exercise? It may for instance have further specifications that are not in your question...
I just added the link to the question. freeCodeCamp tests against several other sentences too, but for some reason not a single test passes. Unless I use a completely different and shortened code which is not my goal. Also I know for a fact that they don't expect a specific structure for the answer as long as it returns the right type of value.
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, i.e. 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.