function CheckValue(value, index, ar) {  
    if (index == 0)  
        return true;  
    else  
        return ar[index - 1] === " ";  
}  

// Create a string.  
var sentence = "The quick brown fox jumps over the lazy dog.";   

// Create an array that contains all characters that follow a space.  
var subset = [].filter.call(sentence, CheckValue);   


document.write(subset);

As per the official doc, I have seen filter method is called upon an array. But here things seem to be messed up. For the first time, I have seen this kind of example using filter method.

I am unable to understand that how this code is working under the hood.

Write your answer…

It's no magic, but might be written in a weird way. The purpose of the code is to get an array of all first letters of new words - separated by one space, though, so this solution is not very robust and I have several ideas how to improve this example... Well, whatever. Let's take a look at the code and what happens there.

First of all, let me add a few comments:

// this function is the filter handler. It returns a boolean:
// true if the value in the array can stay, false if it has to go.
function CheckValue(value, index, ar) {
    // if the value is the first value in the index, it can stay
    // which means that the first letter of the sentence is in the result,
    // which in general makes sense, right :)
    if (index == 0)  
        return true;
    else  
        // in any other case, check if the value at the previous index was a whitespace.
        // if it was, then the current index contains the first letter of a new word
        // hence, if the previous index contained a whitespace, return true, else false.
        return ar[index - 1] === " ";  
}  

// Create a string.  
var sentence = "The quick brown fox jumps over the lazy dog.";   

// Create an array that contains all characters that follow a space.  
var subset = []  // in order to use .filter(), we need an array to call it on.
    .filter // now we can access the filter() method
    .call(
        // however, we want to use it on the string above
        // which is why we use call in order to change the thisArg.
        // By passing a string as thisArg to an array-method,
        // the string is implicitely transformed into an array of characters.
        // So each index contains exactly one letter.
        sentence,
        // in order to filter, all we then have to do is pass the above filter handler
        // and it will check every letter with the logic defined above.
        CheckValue
    )
;

document.write(subset);

Well. Let's improve that. Without changing the stability, instead of using filter, the approach which seems more natural would be to split the sentence into words and then get the first letter of each of them, right?

console.log(
    'The quick brown fox jumps over the lazy dog.'
        .split(/ /)
        .map(word => word[0])
);

but wait, what if someone used a tab instead of a whitespace?

console.log(
    'The quick brown fox jumps over the lazy\tdog.'
        .split(/\s/)
        .map(word => word[0])
);

ok, but what if someone used more than one tab? That would generate empty strings in the result set, which is not right! What about hyphens and the like?

console.log(
    'The quick brown fox jumps over       -  \t    the lazy ; dog.'
        .split(/\s/)
        .filter(word => /[a-z]/i.test(word[0] || ''))
        .map(word => word[0])
);

Yay, finally a legit use-case for filter. It removes all the unwanted stuff from the array. There are even more conditions which have to be met for a robust solution, but is it really that complicated to just get the first letter of each word of a sentence? Can't we simplify all of the above? Well...

console.log(
    'The quick brown fox jumps over       -  \t      the lazy ; dog.'
        .match(/(^|\s)(\w)/g)
        .map(letter => letter[1] ? letter[1] : letter[0])
);

Regex. When working with strings, it usually produces a simple solution. Also it is supported by older browsers. The regex /(^|\s)(\w)/g can be read as "Match all single word-characters and return them as match groups, which are preceded by either the beginning of the string or any whitespace character.". It will match a whitespace (or the beginning of the sentence) and the first letter of a new word - which is why we have to use map to remove the whitespace.

Edit: Yes, I made a mistake. The earlier version of the final improvement only had a .match() call, however that leaves whitespaces in the results. That's not directly obvious to the developer's eye, however it makes a difference for the program, so I fixed it (by sacrificing simpleness). Better have a correct version here than something simple, which is broken.

1 Beer1
Clap2
Star2
Spot On3

This reply is truly above and beyond! Amazing writeup

Reply to this…

Hashnode is building a friendly and inclusive dev community. Come jump on the bandwagon!

  • 💬 A beginner friendly place

  • 🧠 Stay in the loop and grow your knowledge

  • 🍕 >500K developers share programming wisdom here

  • ❤️ Support the growing dev community!

Register ( 500k+ developers strong 👊)