I'm new to Javascript, and don't understand why the output of the following two approaches produce different results.
In the first example (method 1
), I'm starting with an empty string then looping through every word of a sample text and checking if it's an alphanumeric sequence (i.e. word.trim() !== emptyString).
In the second example (method 2
), I'm trying to use the filter
function to do the same thing, by removing any words that are non-alphanumeric (line breaks, spaces, tabs, etc.) and then using the join
command to "glue" everything back together.
Below is my approach:
// Sample Text
// Note the newline characters
let text =
"quoth that of all the kings of earth \n" +
"of men he was mildest and most beloved \n" +
"to his kin the kindest keenest for praise";
// Method 1
let filtered = "";
for (let word of text.split(" ")){
if(word.trim() !== ""){
filtered += word.trim() + " "; // word padding via concatenation
}
}
console.log(filtered, '\n'); // ----------- Output One
// Method 2 - using filter function
let output = text.split(" ").filter(function(word){
return word.trim() !== "" ? word : "";
}).join(" "); // word padding via join() method
console.log(output, '\n'); // ----------- Output Two
The output of the first method is this:
quoth that of all the kings of earth of men he was mildest and most beloved to his kin the kindest keenest for praise
The output of the second method is this:
quoth that of all the kings of earth
of men he was mildest and most beloved
to his kin the kindest keenest for praise
Each approach is using the same word.trim() !== ""
logic to filter, but the second seems to not correctly filter out newline characters?
As a sanity check, I tried the second approach to remove the first word quoth
using the same logical approach as such:
// Sanity Check
let outputTwo = text.split(" ").filter(function(word){
return word !== "quoth" ? word : "";
}).join(" ");
console.log(outputTwo);
The output is as follows:
that of all the kings of earth
of men he was mildest and most beloved
to his kin the kindest keenest for praise
The first word quoth
was removed, as expected.
I don't understand why the newline characters aren't being removed using the second method.
Note: My question is NOT "how to remove newline characters in javascript". I'm aware this might not be the most efficient way to approach this.
Update
Thank you @Robin Zigmond
for pointing out my silly logic. It completely makes sense that the string earth \nof men
would result in [earth, \nof, men]
when using the split()
function.
Also, I can say that the following code, using the map
function as suggested produces the desired result:
// Method 3
let outputThree = text.split(" ").map(
word => word.trim() !== "" ? word.trim() : ""
).join(" ");
console.log(outputThree, '\n');
While similar in logic, note the use of the word.trim()
approach for resulting concatenation. That clearly changes a string such as \nof
into of
.
HOWEVER, when adapting the method 2
from above to incorporate the word.trim()
approach, it still produces the text containing the newlines. Here:
// Method 2.1 - using filter function
let output = text.split(" ").filter(function(word){
return word.trim() !== "" ? word.trim() : "";
}).join(" "); // word padding via join() method
console.log(output, '\n'); // ----------- Output Two.1
It's same logic is being used in each method now (I think?) by way of this line;
word.trim() !== "" ? word.trim() : "";
But the approach using filter
still doesn't seem to pick up the newline character.
Update
Thank you @NikosM —knowing the filter()
function returns a boolean
clears everything up. It's detecting the newline, just not performing any action beyond that.
It's because your string is the following, if one manually does the concatenations:
let text =
"quoth that of all the kings of earth \nof men he was mildest and most beloved \nto his kin the kindest keenest for praise";
Note that the newline characters are directly "next to" the following word, with no space inbetween. So when you call split(" ")
on the strong, you end up with eg. "\nof"
as entries in the array.
This matters because your two methods don't actually do the same thing. The first adds the result of calling .trim()
on each "word", whereas the second simply adds the "word" unchanged, provided it doesn't trim down to the empty string. "\nof"
doesn't do the latter, so you end up with that in the output string, as you are seeing. Whereas in the first code sample, you add "\nof".trim()
, that is "of"
.
Note that you can use the map
method to apply an operation, such as .trim
here, to each element of the array - either before or after the filter.