Search code examples
javascriptreactjsstringloopsstring-comparison

How can I compare two strings and replace matching words with JavaScript?


I am trying to create a function which takes in 2 strings:

- title: "Lorem ipsum dolor sit amet",

- itle_highlighted: "ipsum amet",

and returns one string or array containing the all words in title in addition words defined in the string title_highlighted will have a certain property and replace their matching word in title.

End result should be something like: <h1>Lorem<span style={{color: "orange"}}>impsum</span>dolor sit<span style={{color: "orange"}}>amet</span>/h1>

Output example

My approach so far:

const highlightHeading = (title, title_highlighted) => {
  const title_arr = title.trim().split(/\s+/);
  const title_highlighted_arr = title_highlighted.trim().split(/\s+/);

  for (const element1 of title_arr) {
    console.log(element1);
    for (const element2 of title_highlighted_arr) {
      if (element1 === element2) {
        const highlighted = `<span style={{ color: "orange" }}>${element1}</span>`;
        console.log(highlighted);
      }
    }
  }
};
highlightHeading("Lorem ipsum dolor sit amet", "ipsum amet");

Thanks in advance.


Solution

  • You could create a <HighlightedHeading> component that accepts a color, title, and words.

    const { useMemo, useState } = React;
    
    const tokenize = (str, delim = /\s+/) => str.trim().split(delim);
    
    const toWordArray = (words) => {
      if (Array.isArray(words)) return words;
      if (typeof words === 'string') return tokenize(words);
      return []; // or throw Error
    };
    
    const toWordSet = (words) =>
      new Set(toWordArray(words).map(word => word.toLowerCase()));
    
    const HighlightedHeading = (props) => {
      const { color, title, words } = props;
      const wordSet = useMemo(() => toWordSet(words), [words]);
      return (
        <h2 className="highlighted-text">
          {tokenize(title).map((token) => (
            <React.Fragment>
              {wordSet.has(token)
                ? <span style={{ color }}>{token}</span>
                : token}
              {/* Add spaces for copy-paste */}
              {' '}
            </React.Fragment>
          ))}
        </h2>
      );
    };
    
    const App = () => {
      return (
        <div>
          <HighlightedHeading
            color="yellow"
            title="Lorem ipsum dolor sit amet"
            words="ipsum amet"
          />
        </div>
      );
    };
    
    ReactDOM
      .createRoot(document.getElementById("root"))
        .render(<App title="Example using Hooks:" />);
    *, *::before, *::after {
      box-sizing: border-box;
    }
    
    html, body, #root {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    #root {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      background: #222;
      color: #FFF;
    }
    
    .highlighted-text {
      display: flex;
      gap: 0.5ch; /* Display spaces in HTML */
      margin: 0;
    }
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>