5

Hi I want to create very basic profanity filter in JavaScript.

I've an array called badWords and also I've constant called description. I won't to check whether there is any bad word contains in that description.

This is what I've done upto now.

const badWords = ["Donald Trump","Mr.Burns","Sathan"];

const description = "Mr.Burns entered to the hall."
let isInclude = false;
badWords.forEach(word=>{
  if(description.includes(word)){
  isInclude = true
  }
})

console.log(`Is include`,isInclude)

Only problem is I've to loop through badWords array. Is there a way to get this done without looping through the array?

margherita pizza
  • 6,623
  • 23
  • 84
  • 152
  • 4
    Why would looping over several values of a dataset be a “problem”? – 04FS Jun 05 '19 at 07:44
  • @04FS this badWords list might contain more than 200 words. – margherita pizza Jun 05 '19 at 07:48
  • 4
    And …? Are you just theoretically concerned about performance (hint: don’t), or do you have any _actual_ indication that this makes things measurably or noticeable slow? – 04FS Jun 05 '19 at 07:50
  • 4
    You can shortcut this iteration as soon as you have found *one* match. Use `.some` instead of `.forEach`… – deceze Jun 05 '19 at 07:51
  • I'm also interested if there's a possibility to do this without a loop. There might be cases where similar checks has to be done over 1000s of keywords. and would be super to have it fully optimized :) – Oliver M Grech Jun 05 '19 at 07:56
  • 1
    It looks like you're really considering the performance of a large number of bad words (strings). In which case, I'd suggest looking at regex (regular expressions) since 1 regular expression could do the same task of more than one (hopefully many more) of those bad words. I use https://regex101.com/ for much of my own regex work, and its a valuable learning tool. – John Dunne Jun 05 '19 at 07:58
  • 2
    @JohnDunne To add emphasis to JohnDunne said, regex can also help catch variation of the "bad" words better, so they won't have to be multiple items on the list. – aviya.developer Jun 05 '19 at 08:00
  • Regex *is* a bad word. (Just kidding.) – deceze Jun 05 '19 at 08:06
  • This is a nightmare. Consider the towns of Scunthorpe and Penistone in England. See [The Scunthorpe problem](https://en.wikipedia.org/wiki/Scunthorpe_problem) for a longer list of problems that this sort of idea has thrown up. – Tangentially Perpendicular Mar 15 '23 at 03:32

5 Answers5

6

Use some() - it exits from the loop as soon as a match to the condition is found, as such it's more performant than forEach.

let isInclude = badWords.some(word => description.includes(word));
InSync
  • 4,851
  • 4
  • 8
  • 30
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
2

Here's what the regexp solution looks like:

// https://stackoverflow.com/a/3561711/240443
const reEscape = s => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');

// needs to be done only once
const badWords = ["Donald Trump","Mr.Burns","Sathan"];
const badWordsRE = new RegExp(badWords.map(reEscape).join('|'));

// testing is quick and easy
console.log("Mr.Burns entered to the hall.".match(badWordsRE)); // "Mr.Burns"
console.log("Nothing objectionable".match(badWordsRE));         // null

(If your bad words are actual regexps, like "Mr\.Burns", then leave out the .map(reEscape))

Amadan
  • 191,408
  • 23
  • 240
  • 301
-2

this function i made turns the bad word into **** and if the bad word is 5 letters it will put 5 *'s

(this was made for my chat i coded)

function filter(chat) {
    var cusswords = ["badword1", "badword2"]
    var chat; // define the chat var which is the function parameter
    for(i=0; i < cusswords.length; i++) {
        var length = String(cusswords[i]).length;
        var characters = "";
        for(u=0; u < length; u++) {
            characters = String(characters) + String("*");
        }
        chat = chat.replace(String(cusswords[i]), String(characters));
    }
    console.log(chat)
    return chat;
} 

then you just use a var equal to the text you want to filter in the filter() function.

var cleanChat = filter(chat);

// send(cleanChat) then send it with another function. 
-3

this function first splits sentence with space and makes an array of words now with the first for loop it checks if the badwords array includes any of this words if yes it pushing it to the result array if no it gose to secound loop and it check for combination words also (that might be inside your bad words array like ['bad joe']) and if it found it also pushing it to the result array. then if result array length not be 0 so can say you have some bad words and you can print resualt

const badW = ["Donald Trump", "Mr.Burns", "Sathan"];
const badWordCheker = function (sentence) {
  const words = sentence.trim().split(" ");
  const result = [];

  for (let i = 0; i < words.length; i++) {
    const currentWord = words[i];
    if (badW.includes(currentWord)) {
      result.push(currentWord);
    } else {
      for (let j = i + 1; j < words.length; j++) {
        const nextWords = words.slice(i, j + 1);

        const phrase = nextWords.join(" ");

        if (badW.includes(phrase)) {
          result.push(phrase);
        }
      }
    }
  }

  if (result.length !== 0) {
    return `the bad word you used  : (${result}) `;
  } else {
    return "what you wrote is ok";
  }
};

console.log(badWordCheker("Donald Trump is here and so Sathan ! "));
Dude
  • 1
  • 2
-5

use try catch

const badWords = ['Donald Trump', 'Mr.Burns', 'Sathan']

const description = 'Mr.Burns entered to the hall.'
let isInclude = false
try {
  badWords.forEach(word => {
    if (description.includes(word)) {
      isInclude = true
      throw new Error(word)
    }
  })
} catch (e) {
  console.log(e)
}
Zhou TK
  • 81
  • 1
  • 8