0

I'm working through some beginner Coderbyte problems and I've come across an interesting dilemma. Here's the problem:

"Using the JavaScript language, have the function LongestWord(sen) take the sen parameter being passed and return the largest word in the string. If there are two or more words that are the same length, return the first word from the string with that length. Ignore punctuation and assume sen will not be empty."

Here's my code:

function LongestWord(sen) {
    var myArray = sen.split(" ");
    var lengthOfSubstring = 0;

    for (var i = 0; i < myArray.length; i++) {
        if (myArray[i].length > lengthOfSubstring) {
            lengthOfSubstring = myArray[i].length;
            sen = myArray[i];
        }
    }
    return sen;
}

console.log(LongestWord("Argument goes here"));

My code passes every test unless the argument contains punctuation. Is there anyway to remove or ignore it? Every search brings up regex and very intimidating syntax haha

EDIT: used the match() method on the sen parameter courtesy of @Markus

function LongestWord(sen) {
    var myArray = sen.match(/[a-z]+/gi);
    var lengthOfSubstring = 0;

    for (var i = 0; i < myArray.length; i++) {
        if (myArray[i].length > lengthOfSubstring) {
            lengthOfSubstring = myArray[i].length;
            sen = myArray[i];
        }
    }
    return sen;
}
console.log(LongestWord("Argument goes here"));
jakewies
  • 342
  • 6
  • 18
  • 1
    `str.replace(/\./g, ' ')` – adeneo Apr 26 '15 at 21:39
  • 2
    Don't be intimidated by regex. Embrace it. The alternatives are much uglier and intimidating. – ThisClark Apr 26 '15 at 21:42
  • 1
    @adeneo — The question says **besides** regex (and punctuation encompasses many more characters than the full stop). – Quentin Apr 26 '15 at 21:42
  • Regex is pretty damn fast, super compact and will save you hundreds of lines of coding down the road. And *it's not even that hard to learn*. Don't be intimidated by it! Even after learning just the basics, several string-related problems will become trivial to you. – Shashank Apr 26 '15 at 21:48
  • ok i'm currently reading up on some documentation. My question still stands, out of curiousity. Is regex the only way to accomplish this? – jakewies Apr 26 '15 at 21:49
  • @Quentin - a regex to remove the specific punctuation the OP wants to remove **is** the answer. – adeneo Apr 26 '15 at 21:49
  • 2
    And no, regex is not the only way to achieve this, you could split all the characters into an array, iterate, check for certain characters, and remove each one, but why? – adeneo Apr 26 '15 at 21:50
  • @adeneo purely out of curiousity – jakewies Apr 26 '15 at 21:52
  • Let's stop with the regex debate and start working on an answer to the question, focusing on *besides regex* – ThisClark Apr 26 '15 at 21:53
  • Regex is not nearly as scary as it looks at first. They are extremely useful in many situations. Take a look at the [MDN Regular Expression guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions), it should demystify things a bit. [This article](http://davidwalsh.name/regular-expressions-rest) is also a pretty good intro. There are of course situations where regex is the wrong tool, such as [parsing HTML](http://stackoverflow.com/questions/590747/using-regular-expressions-to-parse-html-why-not). – Useless Code Apr 27 '15 at 09:52

3 Answers3

2

Without regex:

function LongestWord(sen) {
    var wordStart = -1;
    var bestWord = null;
    var bestLength = 0;

    for (var i = 0; i < sen.length; i++) {
        var ch = sen[i];
        if ('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z')
        {
            if (wordStart === -1)
            {
                wordStart = i;
            }
        }
        else
        {
            if (wordStart !== -1)
            {
                var word = sen.substring(wordStart, i);
                if (word.length > bestLength)
                {
                    bestLength = word.length;
                    bestWord = word;
                }
                wordStart = -1;
            }
        }
    }
    if (wordStart !== -1)
    {
        var word = sen.substring(wordStart);
        if (word.length > bestLength)
        {
            bestLength = word.length;
            bestWord = word;
        }
        wordStart = -1;
    }
    return bestWord;
}

With regex:

function LongestWord(sen) {
    var bestWord = null;
    var bestLength = 0;

    var matches = sen.match(/[a-z]+/gi);
    for (var i = 0; i < matches.length; i++)
        var word = matches[i];
        if (word.Length > bestLength)
        {
            bestLength = word.Length;
            bestWord = word;
        }
    }
    return bestWord;
}
Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
  • 1
    Nice. I was about to comment above that doing it without regex would be so much more work. You have done a good job of demonstrating it. Simply changing one line is a much better solution in my opinion. – DonovanM Apr 26 '15 at 21:56
  • I anticipate these are a problem in your solution - Çüéâä – ThisClark Apr 26 '15 at 22:03
  • Or øæåöéåä€$ etc, basically anything that isn't a-z – adeneo Apr 26 '15 at 22:04
  • This is perfect. I integrated the match method into my code and worked like a charm. I'll edit my original post with the refactored code so you can see what i did. I've never seen/used the match method but i'm going to read some doc on it and familiarize myself with regex. Much appreciated! – jakewies Apr 26 '15 at 22:04
  • @ThisClark, @adeneo. Yes. But that is a problem with any solution, since JavaScript doesn't support matching unicode categories (`\p{L}`). You would have to list all the characters that you consider word-characters (or punctuation). – Markus Jarderot Apr 26 '15 at 22:09
1

Here is one way to do it without regex using a filter function that is pretty compact:

function longestWord(sen) {
    // We are using Python's string.punctuation set.
    var punct = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~';
    var wordArr = sen.split(' ');
    var filteredWordArr = wordArr.map(function (word) {
        return word.split('').filter(function (ch) {
            return punct.indexOf(ch) < 0;
        }).join('');
    });
    return wordArr[filteredWordArr.reduce(function (maxIdx, currWord, i, fwa) {
        return currWord.length > fwa[maxIdx].length ? i : maxIdx;
    }, 0)];
}

console.log(longestWord("Çüéâäâ, wouldn't you like to play?")); // wouldn't

This function returns the unfiltered word that has the greatest length after being filtered and compared to other filtered words, which is probably what you want. I noticed that an older version of this code was returning "wouldnt" instead of "wouldn't", but it's fixed now.

Using regex does clean up this code up a bit though. It helps you replace the split, filter, and join operations with a single regex replace operation:

function longestWord(sen) {
    var punct = /[!"#$%&'()*+,\-.\/\\:;<=>?@[\]^_`{\|}~]/g;
    var wordArr = sen.split(' ');
    var filteredWordArr = wordArr.map(function (word) {
        return word.replace(punct, '');
    });
    return wordArr[filteredWordArr.reduce(function (maxIdx, currWord, i, fwa) {
        return currWord.length > fwa[maxIdx].length ? i : maxIdx;
    }, 0)];
}
Shashank
  • 13,713
  • 5
  • 37
  • 63
1

Without regex

function LongestWord(sen) {
    var punct = '\.,-/#!$%^&*;:{}=-_`~()'.split('');

    var words = sen.split(" ").map(function(item) {
        return item.split('').filter(function(char) {
            return punct.indexOf(char) === -1;
        }).join('');
    });

    return words.reduce(function(a, b) {
        return a.length > b.length ? a : b;
    });
}

With regex

function LongestWord(sen) {
    return sen.split(" ").map(function(word) {
        return word.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/gi, '');
    }).reduce(function(a, b) {
        return a.length > b.length ? a : b;
    });
}
adeneo
  • 312,895
  • 29
  • 395
  • 388