Extract/Match specific words from a paragraph in JavaScript

Viewed 563

I'm currently working on a react native (JS based) project in which I need to match and extract Hospitals' names from dynamic paragraphs coming from the backend server. I know about match(), includes() etc but these are not working in this case as names are dynamic and may containing multiple words.

Any suggestions!

2 Answers

You can highlight the words upon rendering the HTML text.

A regular expression can be created from a list of words via:

const regex = new RegExp(`\\b(${words.map(word => `(${word})`).join('|')})\\b`, 'gi');

The raw HTML can be set using the dangerouslySetInnerHTML prop of the <p>.

const highlightWords = ['beef', 'ham', 'pork', 'sausage', 'ribeye', 'ribs'];

class WordHighlighter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { regex: this._updateRegex(this.props.highlightWords), paragraphs: [] };
  };
  
  /* @private */ _updateRegex(words) {
    return new RegExp(`\\b(${words.map(word => `(${word})`).join('|')})\\b`, 'gi');
  }
  
  /* @private */ _highlightWords(paragraph) {
    return paragraph.replace(this.state.regex, `<span class="highlight">$1</span>`);
  }
  
  componentDidMount() {
    fetch('https://baconipsum.com/api/?type=meat-and-filler')
      .then(response => response.json())
      .then(paragraphs => this.setState({ paragraphs }));
  }
  
  componentDidUpdate(prevProps, prevState) {
    const
      curr = JSON.stringify(this.props.highlightWords),
      prev = JSON.stringify(prevProps.highlightWords);
    if (curr !== prev) {
      this.setState({ regex: this._updateRegex(this.props.highlightWords) });
    }
  }
  
  render() {  
    return (
      <div>
        {this.state.paragraphs.map(paragraph => (
          <p dangerouslySetInnerHTML={{ __html: this._highlightWords(paragraph) }} />
        ))}
      </div>
    );
  };
}

ReactDOM.render(<WordHighlighter highlightWords={highlightWords} />, document.querySelector("#app"))
.highlight { background: yellow; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Here is a component implementation of the class above:

const { useEffect, useState } = React;

const words = ['beef', 'ham', 'pork', 'sausage', 'ribeye', 'ribs'];

const updateRegex = (words) =>
  new RegExp(`\\b(${words.map(word => `(${word})`).join('|')})\\b`, 'gi');

const wordHighlighter = (paragraph, regex) =>
  paragraph.replace(regex, `<span class="highlight">$1</span>`);

const WordHighlighter = (props) => {
  const { highlightWords } = props;
  const [ regex, setRegex ] = useState(updateRegex(highlightWords));
  const [ paragraphs, setParagraphs ] = useState([]);
  
  useEffect(() => fetch('https://baconipsum.com/api/?type=meat-and-filler')
    .then(response => response.json())
    .then(json => setParagraphs(json)), []);
  
  useEffect(() => setRegex(updateRegex(highlightWords)), [highlightWords]);
   
  return (
    <div>
      {paragraphs.map(paragraph => (
        <p dangerouslySetInnerHTML={{ __html: wordHighlighter(paragraph, regex) }} />
      ))}
    </div>
  );
}

ReactDOM.render(<WordHighlighter highlightWords={words} />, document.querySelector("#app"))
.highlight { background: yellow; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Here is an example of what I said before.

const par =  "The quick brown fox jumped quickly over the lazy dog.";

const words = [
  "quick",
  "fox",
  "over",
];

function matches(par, words){
  const output = [];
  words.forEach(word => {
    const test = par.split(word);
    if(test.length > 0){
      for(let i = 1; i < test.length; i++){
        output.push(word);
      }
    }
  })
  return output;
}

const ans = matches(par, words);
console.log(ans);

Related