Function to find longest word in a string Write a function called longest which will take a string of space-separated words and will return the longest one.


My code:

function longest(str) {
  var words = arguments.split(" ");
  var words_count = words.length;

  var longest_word_length = 0;

 for(var i = 0; i &lt; words_count; i++){
   if(longest_word_length &lt; words[i].length){
       longest_word_length = words[i].length;
   }
}
return longest_word_length;
}


Running it with this test:

describe("test for longest function functionality", function() {
  it("should return correct output for normal strings", function() {
  expect(longest("A")).toEqual("A");
  expect(longest("I love Avatar")).toEqual("Avatar");
  expect(longest("The stupidities of youth")).toEqual("stupidities");
  });

  it("should return correct output for gibberish", function() {
  expect(longest("hgdydrxtfEq Rradsc tstsa taeWwwecfgdd")).toEqual("hgdydrxtfEq");
  });

 it("should work for sentences with numbers", function() {
 expect(longest("This is a sentence with a number 7685838788")).toEqual("7685838788");
 });
});
Good on you for writing real tests.

Overall, the code seems fine as-is (edit: Actually, no. See David Harkness' comment on the question; arguments.split should be str.split) though I do have a few comments:


The JavaScript convention is to use camelCase for variable names - not snake_case.
Splitting by " " works, but a more comprehensive solution would be to split by /\s+/. That is, split by one or more whitespace characters. That way you avoid zero-length strings in the array if there are two spaces in a row, and it'll also split on newlines and other whitespace. And if you trim() the string first, you'll also avoid empty strings at the start/end if the input string has leading or trailing whitespace.


Also the whole thing can be made more functional (and use some ES6 syntax):

function longest(string) {
  return string
    .trim()
    .split(/\s+/)
    .reduce((longest, word) =&gt; word.length &gt; longest.length ? word : longest);
}


reduce (aka "fold" in other languages), when given no 2nd argument, will use the first element - the first word - in the array as its initial memo. The callback then either reuses that word, or replaces it when it finds one that's longer. Whatever the memo is at the end is what gets returned.



Another approach, much less functional, could be to use String.replace as a "scan" function:

function longest(string) {
  var length = 0;
  var longestWord = "";
  string.replace(/\S+/g, (word) =&gt; {
    if(word.length &gt; length) {
      length = word.length;
      longestWord = word;
    }
    return ""; // for good measure; otherwise all words will be replaced with "undefined" in-memory
  });
  return longestWord;
}


The regex finds any run of non-whitespace character of length 1 or more. It's not terribly pretty, since replace isn't being used "as intended", really, and there are some closure side-effects. It doesn't have the memory consumption of the previous solution however (no array used to hold the split string).