20

I have written a function which receives a sentence and calculates the longest word in that sentence.

function findLongestWord(str) {

  var charArray = str.split(" ");
  var wordArray = [];


  for(var i = 0; i < charArray.length; i++ ) {
    wordArray.push(charArray[i].length);
    wordArray.sort();
    wordArray.reverse();

  }

  return wordArray[0];
}

My function works with inputs such as:

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

But when i pass it:

findLongestWord("What if we try a super-long word such as otorhinolaryngology")

The function returns:

4

Rather than

19
Kōdo no musō-ka
  • 769
  • 1
  • 8
  • 23
  • 9
    `.sort()` doesn't work like you'd expect. Try providing it a callback that will sort your numbers correctly. – Gavin Nov 16 '16 at 13:04
  • 1
    What is the result if you remove the wordArray,reverse(); – Anna Jeanine Nov 16 '16 at 13:04
  • 1
    @AnnaJeanine Without '.reverse()' i get '1' – Kōdo no musō-ka Nov 16 '16 at 13:06
  • 4
    You actually don't need `wordArray` at all. On each step, just compare the current length with `maxLen` (initially set to 0) and update accordingly. – georg Nov 16 '16 at 13:06
  • 2
    You don't need to sort which is `O(n log n)` operation to find a single element by condition. – Yury Tarabanko Nov 16 '16 at 13:07
  • 1
    Try `wordArray.sort(function(a, b) { return b.length - a.length; });` That will sort in descending order. – Gavin Nov 16 '16 at 13:07
  • 1
    Try `str.split(" ").sort(function(a, b) { return a.length < b.length; })[0];` – Rayon Nov 16 '16 at 13:08
  • 4
    You could one line this. `return str.split(' ').reduce(function(prev, curr) { if (curr.length > prev) prev = curr.length; return prev; }, 0);` – Gavin Nov 16 '16 at 13:10
  • 1
    I would recommend using the method that georg mentions, however, if you don't want to do that, you should at least move the sort and reverse method calls to after your loop. As it stands, you're sorting every time you add an element to your wordArray and then reversing it, just to sort it back to the forward order again. Technically, there's no functional issue with this, but it would be confusing to some else who looked at your code, and would run into performance issues if passed in a much longer sentence. – Joey Harwood Nov 16 '16 at 22:15
  • 1
    Side note: `sort` and `reverse` should come after the for loop, not inside it. No need to sort and reverse the array during every iteration! Not that an array of lengths is needed, anyway, as [this answer correctly shows](http://stackoverflow.com/a/40632955/889583). – daiscog Nov 17 '16 at 13:02

11 Answers11

26

Your sort function sorts the array lexically, so you end up with

[1,10,19,2,2,2,3,4,4,4]

reversing that, you get

[4,4,4,3,2,2,2,19,10,1]

where 4 is the first number

You don't need the sorting at all, just use Math.max instead

function findLongestWord(str) {
    return Math.max.apply( null, str.split(" ").map( (x) => x.length) );
}
adeneo
  • 312,895
  • 29
  • 395
  • 388
25

TL;DR

Your numbers are getting sorted as strings.

To get them sorted as numbers, in descending order, in your function you should instead do:

wordArray.sort(function(a, b) { return b - a; });

EXPLANATION

According to the docs:

The sort() method sorts the elements of an array in place and returns the array. The sort is not necessarily stable. The default sort order is according to string Unicode code points.

[...]

Syntax

arr.sort()

arr.sort(compareFunction)

Parameters

compareFunction Optional

Specifies a function that defines the sort order. If omitted, the array is sorted according to each character's Unicode code point value, according to the string conversion of each element.

Emphasis mine, so you end up with something like this:

var str = "What if we try a super-long word such as otorhinolaryngology";
var charArray = str.split(" ");
// now charArray == ["What", "if", "we", "try", "a", "super-long", "word", "such", "as", "otorhinolaryngology"]
// when you take the length of each word and end up with
var wordArray = [4, 2, 2, 3, 1, 10, 4, 4, 2, 19];
// and if you use plain wordArray.sort() without specific sort function you get
wordArray = [1, 10, 19, 2, 2, 2, 3, 4, 4, 4];
// and once reversed it is
wordArray = [4, 4, 4, 3, 2, 2, 2, 19, 10, 1];
// this is why you end up with wordArray[0] == 4

You could also implement the whole function as a one-liner:

function findLongestWord(str) {
  return str.split(/\s+/).sort(function(a, b) { return b.length - a.length; })[0].length;
}

console.log("Longest word length = ", findLongestWord("The default sort order is according to string Unicode code points"));

console.log("Longest word length = ", findLongestWord("What if we try a super-long word such as otorhinolaryngology"));
Matteo Tassinari
  • 18,121
  • 8
  • 60
  • 81
15

A little different from your code, but this should have the same outcome!

function longestWord(string) {
    var str = string.split(" ");
    var longest = 0;
    for (var i = 0; i < str.length; i++) {
        if (longest < str[i].length) {
            longest = str[i].length;
        }
    }
    return longest;
}

console.log(longestWord("The quick brown fox jumped over the lazy dog"));
console.log(longestWord("What if we try a super-long word such as otorhinolaryngology"));
georg
  • 211,518
  • 52
  • 313
  • 390
Anna Jeanine
  • 3,975
  • 10
  • 40
  • 74
  • 4
    Thanks for fixing! This is the correct way to do that -- without building the silly "array of lengths". – georg Nov 16 '16 at 13:14
6

You can get an array of lengths of words and then use Math.max.apply

function findLongestWord(str){
  return Math.max.apply(null, str.split(" ").map(x=>x.length));
}

var l = findLongestWord("What if we try a super-long word such as otorhinolaryngology")

console.log(l)
Rajesh
  • 24,354
  • 5
  • 48
  • 79
4

function findLongestWord(str) {
  return str.split(' ').reduce((m, w) => Math.max(m, w.length), 0);
}

var result = findLongestWord('The quick brown fox jumped over the lazy dog');
console.log(result);
Yosvel Quintero
  • 18,669
  • 5
  • 37
  • 46
4

a better approach to the problem (in my opinion) using map and max:

function findLongestWord(str) {
    return Math.max.apply(null, str.split(" ").map(function(word){
        return word.length;
    }));
}
pwolaq
  • 6,343
  • 19
  • 45
3

Shortest way:

console.log(
  'What if we try a super-long word such as otorhinolaryngology'
  .split(' ')
  .sort(function(a, b) {
    return b.length - a.length
  })[0].length
);

Or as a function:

function returnLongest(str) {
  return str
    .split(' ')
    .sort(function(a, b) {
      return b.length - a.length
    })[0].length;
}
console.log(returnLongest('What if we try a super-long word such as otorhinolaryngology'))
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
2

You do not have to use an array. If you just want to save the longest word, just compare the longest size with the current word size

function findLongestWord(str) {
  var charArray = str.split(" ");
  var longestWord = 0;

  for (var i = 0; i < charArray.length; i++) {
    let l = charArray[i].length;
    if (l > longestWord)
      longestWord = l;
  }
  return longestWord;
}

console.log(findLongestWord("The quick brown fox jumped over the lazy dog"));
console.log(findLongestWord("What if we try a super-long word such as otorhinolaryngology"));
Weedoze
  • 13,683
  • 1
  • 33
  • 63
1

The sort function will sort the array in a lexicographical way, which is not what you want here. You need to pass the sorting method also, if you want a perfect ascending sorting for numbers. Also, you are sorting and reversing the array in the for loop, so you are doing it every time an item is added.

What you should do instead is:

for(var i = 0; i < charArray.length; i++ ) {
    wordArray.push(charArray[i].length);
  }

wordArray.sort(ascendingSort);
wordArray.reverse();

function ascendingSort(a, b) {
    return a - b;
}

return wordArray[0];
Catalin Iancu
  • 722
  • 5
  • 18
  • It would appear so. I mistakenly thought that lexicographical sorting would be enough, since those are numbers, not just strings. I will edit my answer to avoid confusion. – Catalin Iancu Nov 16 '16 at 13:26
0

you need to pass a function to sort:

function findLongestWord(str) {

  var charArray = str.split(" ");
  var wordArray = [];


  for(var i = 0; i < charArray.length; i++ ) {
    wordArray.push(charArray[i].length);
    wordArray.sort(function(a,b){
        return a > b;
    });
    wordArray.reverse();

  }

  return wordArray[0];
}

var longest = findLongestWord("What if we try a super-long word such as otorhinolaryngology");
hello_world
  • 442
  • 3
  • 7
0

Instead of pushing the lengths and sorting it , Please try the following

 function findLongestWord(str) {

  var charArray = str.split(" ");
  var longestWordLength = 0;
  var longestWord = "";

  for(var i = 0; i < charArray.length; i++ ) {
    if(charArray[i].length > longestWordLength){
      longestWordLength = charArray[i].length;
      longestWord = charArray[i]
    }
  }
  return {longestWord , longestWordLength};
}
Vignesh Murugan
  • 575
  • 5
  • 18