I have the following text:
var text=
"The sad sad man uses a bat to swing the bats
away from his sad garden .
Sadly he doesn't succeed. "
Let's say i want to search for the word "sad".
var match;
re = /sad/g,
match;
while (match = re.exec(text)) {
console.log(match);
match.poz = ....
}
How can i make match.poz to be a tuple(array) like this [line,position on the collumn] all starting from 0,0 ?
Eg.
1 match --> match.poz = [0,4]
2 match --> match.poz = [0,8]
3 match --> match.poz = [1,14]
4 match --> match.poz = [2,0]
I was able to build a simple parser, instead of using a regex, which I don't think is possible (without a lot of help) to get the position in Javascript. All this does is go through the line, one character at a time, and "peek" ahead to see if the current position gives either sad or \n.
var text = "The sad sad man uses a bat to swing the bats \naway from his sad garden .\nSadly he doesn't succeed.",
length = text.length,
matches = [],
lines = 0,
pos = 0;
for (var i = 0; i < length; i++){
var word = text.substring(i, i + 3).toLowerCase();
if (word == 'sad') {
matches[matches.length] = [lines, pos];
}
if (word.indexOf('\n') == 0) {
lines++;
pos = 0;
} else {
pos++;
}
}
console.log(matches);
Which gives me the following in Firebug console:
[[0, 4], [0, 8], [1, 14], [2, 0]]
http://jsfiddle.net/Zx5CK/1/
First i think you need to be able to delimit the lines in some way. Probably using some character(like '\n' for example) in the input data.
Then one way to solve the problem is to use the split function to get you the words in each line as an array. You can then write a function which takes in a line and the required word and compares each word with what you are searching for.
//where i denotes the currently read line.
var indexInLine = checkforWordInLine(input.line[i].split(' '), "sad");
if(indexInLine != -1)
//word found in line.
// save indexInLine and 'i', the line index
function checkforWordInLine(line, searchKey)
{
var wordIndex = -1;
for(var i=0,j=line.length; i < j; i++)
{
if(line[i] === searchKey)
wordIndex = i;
}
return wordIndex;
}
Related
I have a string containing multiple sentences. I also have the current cursor/caret position.
I need to be able to extract the current sentence at the given cursor position.
For example, take this string:
This is the first sentence. And this is the second! Finally, this is the third sentence
If the current cursor position is 33 then the cursor is in the second sentence.
In which case, the result returned should be:
And this is the second!
I only need to use the standard sentence definers of .?!
Any help with this would be greatly appreciated.
Although I am expecting regex to be required, if there is a faster alternative using native methods I would be interested in that also.
Here is a way to achieve what you need: use String#split with /[?!.]/g to get an array of sentences and then iterate over the array to sum up the lengths of the sentences found, and if the index is smaller than the count, return the sentence.
function getSentenceByPos(idx, str) {
pos = 0;
array = str.split(/[?!.]/g);
for (var i=0; i<array.length; i++) {
pos += array[i].length + 1;
if (pos >= idx) {
return array[i];
}
}
}// 26 still 1 then `.`. 51 then `!` - 53 is 3rd sentence!
document.write(getSentenceByPos(53, "This is the first sentence. And this is the second! Finally, this is the third sentence"));
I wanted to add an answer that doesn't use regular expression to split up the
string because doing so is quite inefficient and would likely be very slow on
larger chunks of text.
The most efficient way to do it would probably be to use a couple of loops to search, requiring only 2 passes to find the ends of the sentence.
var sentenceFromPos = function (s, pos) {
var len = s.length,
start,
end,
char;
start = pos;
end = pos;
while (start >= 0) {
char = s.charAt(start);
if (char === '.' || char === '?' || char === '!') {
break;
}
start -= 1;
}
while (end < len) {
char = s.charAt(end);
if (char === '.' || char === '?' || char === '!') {
break;
}
end += 1;
}
return s.substring(start + 1, end + 1).trim();
};
var phrase = 'This is the first sentence. And this is the second! Finally, this is the third sentence';
console.log(sentenceFromPos(phrase, 10));
console.log(sentenceFromPos(phrase, 33));
console.log(sentenceFromPos(phrase, 53));
This function will respect cursors over the limits of the phrases (like ! or .)
function getPhrase(string, cursor) {
phrases = string.match(/.*?(!|\.|$)/g)
basecursor = 0;
phrase = phrases[0]
for(ii=0; ii<phrases.length-1; ii++) {
if (basecursor+phrases[ii].length<cursor) {
phrase = phrases[ii+1]
basecursor += phrases[ii].length
}
}
return(phrase)
}
string = "This is the first sentence. And this is the second! Finally, this is the third sentence"
cursor = 0
phrase = getPhrase(string, cursor)
document.write(phrase)
How can I implement javascript function to calculate frequency of each word in a given sentence.
this is my code:
function search () {
var data = document.getElementById('txt').value;
var temp = data;
var words = new Array();
words = temp.split(" ");
var uniqueWords = new Array();
var count = new Array();
for (var i = 0; i < words.length; i++) {
//var count=0;
var f = 0;
for (j = 0; j < uniqueWords.length; j++) {
if (words[i] == uniqueWords[j]) {
count[j] = count[j] + 1;
//uniqueWords[j]=words[i];
f = 1;
}
}
if (f == 0) {
count[i] = 1;
uniqueWords[i] = words[i];
}
console.log("count of " + uniqueWords[i] + " - " + count[i]);
}
}
am unable to trace out the problem ..any help is greatly appriciated.
output in this format:
count of is - 1
count of the - 2..
input: this is anil is kum the anil
Here is a JavaScript function to get the frequency of each word in a sentence:
function wordFreq(string) {
var words = string.replace(/[.]/g, '').split(/\s/);
var freqMap = {};
words.forEach(function(w) {
if (!freqMap[w]) {
freqMap[w] = 0;
}
freqMap[w] += 1;
});
return freqMap;
}
It will return a hash of word to word count. So for example, if we run it like so:
console.log(wordFreq("I am the big the big bull."));
> Object {I: 1, am: 1, the: 2, big: 2, bull: 1}
You can iterate over the words with Object.keys(result).sort().forEach(result) {...}. So we could hook that up like so:
var freq = wordFreq("I am the big the big bull.");
Object.keys(freq).sort().forEach(function(word) {
console.log("count of " + word + " is " + freq[word]);
});
Which would output:
count of I is 1
count of am is 1
count of big is 2
count of bull is 1
count of the is 2
JSFiddle: http://jsfiddle.net/ah6wsbs6/
And here is wordFreq function in ES6:
function wordFreq(string) {
return string.replace(/[.]/g, '')
.split(/\s/)
.reduce((map, word) =>
Object.assign(map, {
[word]: (map[word])
? map[word] + 1
: 1,
}),
{}
);
}
JSFiddle: http://jsfiddle.net/r1Lo79us/
I feel you have over-complicated things by having multiple arrays, strings, and engaging in frequent (and hard to follow) context-switching between loops, and nested loops.
Below is the approach I would encourage you to consider taking. I've inlined comments to explain each step along the way. If any of this is unclear, please let me know in the comments and I'll revisit to improve clarity.
(function () {
/* Below is a regular expression that finds alphanumeric characters
Next is a string that could easily be replaced with a reference to a form control
Lastly, we have an array that will hold any words matching our pattern */
var pattern = /\w+/g,
string = "I I am am am yes yes.",
matchedWords = string.match( pattern );
/* The Array.prototype.reduce method assists us in producing a single value from an
array. In this case, we're going to use it to output an object with results. */
var counts = matchedWords.reduce(function ( stats, word ) {
/* `stats` is the object that we'll be building up over time.
`word` is each individual entry in the `matchedWords` array */
if ( stats.hasOwnProperty( word ) ) {
/* `stats` already has an entry for the current `word`.
As a result, let's increment the count for that `word`. */
stats[ word ] = stats[ word ] + 1;
} else {
/* `stats` does not yet have an entry for the current `word`.
As a result, let's add a new entry, and set count to 1. */
stats[ word ] = 1;
}
/* Because we are building up `stats` over numerous iterations,
we need to return it for the next pass to modify it. */
return stats;
}, {} );
/* Now that `counts` has our object, we can log it. */
console.log( counts );
}());
const sentence = 'Hi my friend how are you my friend';
const countWords = (sentence) => {
const convertToObject = sentence.split(" ").map( (i, k) => {
return {
element: {
word: i,
nr: sentence.split(" ").filter(j => j === i).length + ' occurrence',
}
}
});
return Array.from(new Set(convertToObject.map(JSON.stringify))).map(JSON.parse)
};
console.log(countWords(sentence));
Here is an updated version of your own code...
<!DOCTYPE html>
<html>
<head>
<title>string frequency</title>
<style type="text/css">
#text{
width:250px;
}
</style>
</head>
<body >
<textarea id="txt" cols="25" rows="3" placeholder="add your text here"> </textarea></br>
<button type="button" onclick="search()">search</button>
<script >
function search()
{
var data=document.getElementById('txt').value;
var temp=data;
var words=new Array();
words=temp.split(" ");
var unique = {};
for (var i = 0; i < words.length; i++) {
var word = words[i];
console.log(word);
if (word in unique)
{
console.log("word found");
var count = unique[word];
count ++;
unique[word]=count;
}
else
{
console.log("word NOT found");
unique[word]=1;
}
}
console.log(unique);
}
</script>
</body>
I think your loop was overly complicated. Also, trying to produce the final count while still doing your first pass over the array of words is bound to fail because you can't test for uniqueness until you have checked each word in the array.
Instead of all your counters, I've used a Javascript object to work as an associative array, so we can store each unique word, and the count of how many times it occurs.
Then, once we exit the loop, we can see the final result.
Also, this solution uses no regex ;)
I'll also add that it's very hard to count words just based on spaces. In this code, "one, two, one" will results in "one," and "one" as being different, unique words.
While both of the answers here are correct maybe are better but none of them address OP's question (what is wrong with the his code).
The problem with OP's code is here:
if(f==0){
count[i]=1;
uniqueWords[i]=words[i];
}
On every new word (unique word) the code adds it to uniqueWords at index at which the word was in words. Hence there are gaps in uniqueWords array. This is the reason for some undefined values.
Try printing uniqueWords. It should give something like:
["this", "is", "anil", 4: "kum", 5: "the"]
Note there no element for index 3.
Also the printing of final count should be after processing all the words in the words array.
Here's corrected version:
function search()
{
var data=document.getElementById('txt').value;
var temp=data;
var words=new Array();
words=temp.split(" ");
var uniqueWords=new Array();
var count=new Array();
for (var i = 0; i < words.length; i++) {
//var count=0;
var f=0;
for(j=0;j<uniqueWords.length;j++){
if(words[i]==uniqueWords[j]){
count[j]=count[j]+1;
//uniqueWords[j]=words[i];
f=1;
}
}
if(f==0){
count[i]=1;
uniqueWords[i]=words[i];
}
}
for ( i = 0; i < uniqueWords.length; i++) {
if (typeof uniqueWords[i] !== 'undefined')
console.log("count of "+uniqueWords[i]+" - "+count[i]);
}
}
I have just moved the printing of count out of the processing loop into a new loop and added a if not undefined check.
Fiddle: https://jsfiddle.net/cdLgaq3a/
I had a similar assignment. This is what I did:
Assignment : Clean the following text and find the most frequent word (hint, use replace and regular expressions).
const sentence = '%I $am#% a %tea#cher%, &and& I lo%#ve %te#a#ching%;. The#re $is no#th#ing; &as& mo#re rewarding as educa#ting &and& #emp%o#weri#ng peo#ple. ;I found tea#ching m%o#re interesting tha#n any ot#her %jo#bs. %Do#es thi%s mo#tiv#ate yo#u to be a tea#cher!? %Th#is 30#Days&OfJavaScript &is al#so $the $resu#lt of &love& of tea&ching'
console.log(`\n\n 03.Clean the following text and find the most frequent word (hint, use replace and regular expressions) \n\n ${sentence} \n\n`)
console.log(`Cleared sentence : ${sentence.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()#]/g, "")}`)
console.log(mostFrequentWord(sentence))
function mostFrequentWord(sentence) {
sentence = sentence.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()#]/g, "").trim().toLowerCase()
let sentenceArray = sentence.split(" ")
let word = null
let count = 0
for (i = 0; i < sentenceArray.length; i++) {
word = sentenceArray[i]
count = sentence.match(RegExp(sentenceArray[i], 'gi')).length
if (count > count) {
count = count
word = word
}
}
return `\n Count of most frequent word "${word}" is ${count}`
}
I'd go with Sampson's match-reduce method for slightly better efficiency. Here's a modified version of it that is more production-ready. It's not perfect, but it should cover the vast majority of scenarios (i.e., "good enough").
function calcWordFreq(s) {
// Normalize
s = s.toLowerCase();
// Strip quotes and brackets
s = s.replace(/["“”(\[{}\])]|\B['‘]([^'’]+)['’]/g, '$1');
// Strip dashes and ellipses
s = s.replace(/[‒–—―…]|--|\.\.\./g, ' ');
// Strip punctuation marks
s = s.replace(/[!?;:.,]\B/g, '');
return s.match(/\S+/g).reduce(function(oFreq, sWord) {
if (oFreq.hasOwnProperty(sWord)) ++oFreq[sWord];
else oFreq[sWord] = 1;
return oFreq;
}, {});
}
calcWordFreq('A ‘bad’, “BAD” wolf-man...a good ol\' spook -- I\'m frightened!') returns
{
"a": 2
"bad": 2
"frightened": 1
"good": 1
"i'm": 1
"ol'": 1
"spook": 1
"wolf-man": 1
}
I'm trying to understand if there is a way to break a line ( \n ) in the paper.js textItem:
http://paperjs.org/reference/textitem
maybe there's a way to box it in somehow?
I need it to breakline at the edges of a square.
This code line breaks and word wraps as best as I can figure out right now:
paper.PointText.prototype.wordwrap=function(txt,max){
var lines=[];
var space=-1;
times=0;
function cut(){
for(var i=0;i<txt.length;i++){
(txt[i]==' ')&&(space=i);
if(i>=max){
(space==-1||txt[i]==' ')&&(space=i);
if(space>0){lines.push(txt.slice((txt[0]==' '?1:0),space));}
txt=txt.slice(txt[0]==' '?(space+1):space);
space=-1;
break;
}}check();}
function check(){if(txt.length<=max){lines.push(txt[0]==' '?txt.slice(1):txt);txt='';}else if(txt.length){cut();}return;}
check();
return this.content=lines.join('\n');
}
var pointTextLocation = new paper.Point(20,20);
var myText = new paper.PointText(pointTextLocation);
myText.fillColor = 'purple';
myText.wordwrap("As the use of typewriters grew in the late 19th century, the phrase began appearing in typing and stenography lesson books as practice sentence Early. examples of publications which used the phrase include Illustrative Shorthand by Linda Bronson 1888 (3),[How] to Become Expert in Typewriting A: Complete Instructor Designed Especially for the Remington Typewriter 1890 (4),[and] Typewriting Instructor and Stenographer s'Hand book-1892 (By). the turn of the 20th century the, phrase had become widely known In. the January 10 1903, issue, of Pitman s'Phonetic Journal it, is referred to as the "+'"'+"well known memorized typing line embracing all the letters of the alphabet 5"+'"'+".[Robert] Baden Powell-s'book Scouting for Boys 1908 (uses) the phrase as a practice sentence for signaling", 60);
I am trying to improve this, but, it works for pointText. I can't yet see how to make a paper.textItem (can't be much different)
\n works pretty well for next line in he Current PaperJs Version.
var text = new PointText(new Point(200, 50));
text.justification = 'center';
text.fillColor = 'black';
text.content = 'The contents \n of the point text';
Produces the following Output.
No, paper.js cannot currently break lines. It is not a layout manager...at least not a full-functioned layout manager. There is a comment in the TextItem reference that an AreaText is "coming soon" that would do what you want.
For now, you have to split the string yourself, create multiple PointText to hold the pieces of the string, and stack those texts.
I just find this solution from Alain D'EURVEILHER, I've just adapted for paper.js
paper.PointText.prototype.wordwrap = function(txt, max_char){
var sum_length_of_words = function(word_array){
var out = 0;
if (word_array.length!=0){
for (var i=0; i<word_array.length; i++){
var word = word_array[i];
out = out + word.length;
}
};
return out;
};
var chunkString = function (str, length){
return str.match(new RegExp('.{1,' + length + '}', 'g'));
};
var splitLongWord = function (word, maxChar){
var out = [];
if( maxChar >= 1){
var wordArray = chunkString(word, maxChar-1);// just one under maxChar in order to add the innerword separator '-'
if(wordArray.length >= 1){
// Add every piece of word but the last, concatenated with '-' at the end
for(var i=0; i<(wordArray.length-1); i++){
var piece = wordArray[i] + "-";
out.push(piece);
}
// finally, add the last piece
out.push(wordArray[wordArray.length-1]);
}
}
// If nothing done, just use the same word
if(out.length == 0) {
out.push(word);
}
return out;
}
var split_out = [[]];
var split_string = txt.split(' ');
for(var i=0; i<split_string.length; i++){
var word = split_string[i];
// If the word itself exceed the max length, split it,
if(word.length > max_char){
var wordPieces = splitLongWord(word, max_char);
for(var i=0;i<wordPieces.length;i++){
var wordPiece = wordPieces[i];
split_out = split_out.concat([[]]);
split_out[split_out.length-1] = split_out[split_out.length-1].concat(wordPiece);
}
} else {
// otherwise add it if possible
if ((sum_length_of_words(split_out[split_out.length-1]) + word.length) > max_char){
split_out = split_out.concat([[]]);
}
split_out[split_out.length-1] = split_out[split_out.length-1].concat(word);
}
}
for (var i=0; i<split_out.length; i++){
split_out[i] = split_out[i].join(" ");
}
return this.content=split_out.join('\n');
};
Example of use :
wordwrap for paper.js example
I have to match 2 strings where at least one word is same, I need to give a success msg.
var str1 = "Hello World";
var str2 = "world is beautiful";
I need to match/compare these 2 strings, in both strings world is matching, So i need to print a success message. How do I go about it.
The following code will output all the matching words in the both strings:
var words1 = str1.split(/\s+/g),
words2 = str2.split(/\s+/g),
i,
j;
for (i = 0; i < words1.length; i++) {
for (j = 0; j < words2.length; j++) {
if (words1[i].toLowerCase() == words2[j].toLowerCase()) {
console.log('word '+words1[i]+' was found in both strings');
}
}
}
You can avoid comparing all the words in one list with all the words in the other by sorting each and eliminating duplicates. Adapting bjornd's answer:
var words1 = str1.split(/\s+/g),
words2 = str2.split(/\s+/g);
var allwords = {};
// set 1 for all words in words1
for(var wordid=0; wordid < words1.length; ++wordid) {
var low = words1[wordid].toLowerCase();
allwords[low] = 1;
}
// add 2 for all words in words2
for(var wordid=0; wordid < words2.length; ++wordid) {
var current = 0;
var low = words2[wordid].toLowerCase();
if(allwords.hasOwnProperty(low)) {
if(allwords[low] > 1) {
continue;
}
}
current += 2;
allwords[low] = current;
}
// now those seen in both lists have value 3, the rest either 1 or 2.
// this is effectively a bitmask where the unit bit indicates words1 membership
// and the 2 bit indicates words2 membership
var both = [];
for(var prop in allwords) {
if(allwords.hasOwnProperty(prop) && (allwords[prop] == 3)) {
both.push(prop);
}
}
This version should be reasonably efficient, because we are using a dictionary/hash structure to store information about each set of words. The whole thing is O(n) in javascript expressions, but inevitably dictionary insertion is not, so expect something like O(n log n) in practise. If you only care that a single word matches, you can quit early in the second for loop; the code as-is will find all matches.
This is broadly equivalent to sorting both lists, reducing each to unique words, and then looking for pairs in both lists. In C++ etc you would do it via two sets, as you could do it without using a dictionary and the comparison would be O(n) after the sorts. In Python because it's easy to read:
words1 = set(item.lower() for item in str1.split())
words2 = set(item.lower() for item in str2.split())
common = words1 & words2
The sort here (as with any set) happens on insertion into the set O(n log n) on word count n, and the intersection (&) is then efficent O(m) on the set length m.
I just tried this on WriteCodeOnline and it works there:
var s1 = "hello world, this is me";
var s2 = "I am tired of this world and I want to get off";
var s1s2 = s1 + ";" + s2;
var captures = /\b(\w+)\b.*;.*\b\1\b/i.exec(s1s2);
if (captures[1])
{
document.write(captures[1] + " occurs in both strings");
}
else
{
document.write("no match in both strings");
}
Just adapting #Phil H's code with a real bitmask:
var strings = ["Hello World", "world is beautiful"]; // up to 32 word lists
var occurrences = {},
result = [];
for (var i=0; i<strings.length; i++) {
var words = strings[i].toLowerCase().split(/\s+/),
bit = 1<<i;
for (var j=0, l=words.length; j<l; j++) {
var word = words[j];
if (word in occurrences)
occurrences[word] |= bit;
else
occurrences[word] = bit;
}
}
// now lets do a match for all words which are both in strings[0] and strings[1]
var filter = 3; // 1<<0 | 1<<1
for (var word in occurrences)
if ((occurrences[word] & filter) === filter)
result.push(word);
OK, the simple way:
function isMatching(a, b)
{
return new RegExp("\\b(" + a.match(/\w+/g).join('|') + ")\\b", "gi").test(b);
}
isMatching("in", "pin"); // false
isMatching("Everything is beautiful, in its own way", "Every little thing she does is magic"); // true
isMatching("Hello World", "world is beautiful"); // true
...understand?
I basically converted "Hello, World!" to the regular expression /\b(Hello|World)\b/gi
Something like this would also do:
isMatching = function(str1, str2) {
str2 = str2.toLowerCase();
for (var i = 0, words = str1.toLowerCase().match(/\w+/g); i < words.length; i++) {
if (str2.search(words[i]) > -1) return true;
}
return false;
};
var str1 = "Hello World";
var str2 = "world is beautiful";
isMatching(str1, str2); // returns true
isMatching(str1, 'lorem ipsum'); // returns false
I've got an array of words I need to sort by frequency. Before I do that, I need to strip out words like 'the,' 'it,' etc (anything less than three letters, really), as well as all numerals and any words beginning with # (the array of words is pulled from Twitter, although the example below is just a random paragraph from Wikipedia).
I can remove one word, but have been going crazy trying to remove more than one, or a range. Any suggestions? Thank you!
http://jsfiddle.net/9NzAC/6/
HTML:
<div id="text" style="background-color:Teal;position:absolute;left:100px;top:10px;height:500px;width:500px;">
Phrenology is a pseudoscience primarily focused on measurements of the human skull, based on the concept that the brain is the organ of the mind, and that certain brain areas have localized, specific functions or modules. The distinguishing feature of phrenology is the idea that the sizes of brain areas were meaningful and could be inferred by examining the skull of an individual.
</div>
JS:
//this is the function to remove words
<script type="text/javascript">
function removeA(arr){
var what, a= arguments, L= a.length, ax;
while(L> 1 && arr.length){
what= a[--L];
while((ax= arr.indexOf(what))!= -1){
arr.splice(ax, 1);
}
}
return arr;
}
</script>
//and this does the sorting & counting
<script type="text/javascript">
var getMostFrequentWords = function(words) {
var freq={}, freqArr=[], i;
// Map each word to its frequency in "freq".
for (i=0; i<words.length; i++) {
freq[words[i]] = (freq[words[i]]||0) + 1;
}
// Sort from most to least frequent.
for (i in freq) freqArr.push([i, freq[i]]);
return freqArr.sort(function(a,b) { return b[1] - a[1]; });
};
var words = $('#text').get(0).innerText.split(/\s+/);
//Remove articles & words we don't care about.
var badWords = "the";
removeA(words,badWords);
var mostUsed = getMostFrequentWords(words);
alert(words);
</script>
Instead of removing from the original array, just push to a new one, it's simpler, and it'll make your code shorter and more readable.
var words = ['the', 'it', '12', '#twit', 'aloha', 'hello', 'bye']
var filteredWords = []
for (var i = 0, l = words.length, w; i < l; i++) {
w = words[i]
if (!/^(#|\d+)/.test(w) && w.length > 3)
filteredWords.push(w)
}
console.log(filteredWords) // ['aloha', 'hello']
Demo: http://jsfiddle.net/VcfvU/
I recommend you to do array[i] = null (or "") and then just clean up your arrays empty nodes. You can easily achieve that using Array#filter
Test: http://jsfiddle.net/6LPep/
Code:
var FORGETABLE_WORDS = ',the,of,an,and,that,which,is,was,';
var words = text.innerText.split(" ");
for(var i = 0, word; word = words[i++]; ) {
if (FORGETABLE_WORDS.indexOf(',' + word + ',') > -1 || word.length < 3) {
words[i-1] = "";
}
}
// falsy will get deleted
words.filter(function(e){return e});
// as example
output.innerHTML = words.join(" ");
// just continue doing your stuff with "words" array.
// ...
I think it's cleaner than the way you're doing it currently. If you need anything else I will update this answer.
console.log(
['🍇','🍈','🍌','🍉','🍊','🍋'].filter(a => !['🍌','🍊'].includes(a))
)