Search code examples
javascriptalgorithmmaps

Not entering the if block


const words = [
  "a",
  "alien",
  "born",
  "less",
  "lien",
  "never",
  "nevertheless",
  "new",
  "newborn",
  "the",
  "zebra",
  "zebra",
];
let compoundArr = [];
let memo = new Map();

setFixes = () => {
  for (let word of words) {
    for (let i = 1; i < word.length; i++) {
      const prefix = word.substring(0, i);
      const suffix = word.substring(i);
      if (memo.get(prefix)) return;
      else {
        if (words.includes(prefix)) memo.set(prefix, true);
      }
      if (memo.get(suffix)) return;
      else {
        if (words.includes(suffix)) memo.set(suffix, true);
      }
    }
  }
};

findCompound = () => {
  setFixes();
  for (let word of words) {
    for (let i = 1; i < word.length; i++) {
      const prefix = word.substring(0, i);
      const suffix = word.substring(i);
      if (memo.get(prefix) === true && memo.get(suffix) === true) {
        compoundArr.push(word);
      }
    }
  }
  return compoundArr;
};

findCompound();
console.log(compoundArr);

Hi, I am using a map here to store the prefixes and suffixes to avoid searching for same characters and bigger parts if possible. However I noticed that it never reads from the stored values, it skips this 'if (memo.get(prefix)) return' and 'if (memo.get(suffix)) return' part and moves to searching in the words array again. How can we solve this issue?


Solution

  • Here are some issues and remarks:

    • The function ends when a return is executed, so as soon as a prefix/suffix is found to already be in the Map, the function stops any further processing. Instead of return you'll want to just skip the part that writes to the Map for that particular string only.

    • As your code only ever uses and checks for the value true in the Map, you can do with just a Set.

    • Your function variables are implicitly declared as globals. It is better practice to use const to define them, or use the function statement.

    • Use function parameters so that it is clear which variables might get used by them. And if the function creates a data structure, then have it return it (instead of mutating a global variable). Leave it to the caller to assign the function result to its own variables (which might then be global).

    • To avoid scanning the words array repeatedly, it would be better to turn that array into a Set once, and then use has instead of includes.

    • As a compound word might consist of words that occur multiple times as prefixes and suffixes, you'll want the list of compound words to also be collected as a Set -- to avoid duplicates. You can turn it into an array as a final step.

    const setFixes = (words) => {
      const wordSet = new Set(words); // To speed up look-up
      const fixes = new Set(); // Instead of Map
      for (const word of words) {
        for (let i = 1; i < word.length; i++) {
          const prefix = word.substring(0, i);
          const suffix = word.substring(i);
          // Don't exit the function here -- just skip
          if (wordSet.has(prefix)) fixes.add(prefix);
          if (wordSet.has(suffix)) fixes.add(suffix);
        }
      }
      return fixes; // Return it
    };
    
    const findCompound = (words) => {
      const fixes = setFixes(words);
      const compounds = new Set; // Local; and avoid duplicates
      for (const word of words) {
        for (let i = 1; i < word.length; i++) {
          const prefix = word.substring(0, i);
          const suffix = word.substring(i);
          if (fixes.has(prefix) && fixes.has(suffix)) {
            compounds.add(word);
          }
        }
      }
      return [...compounds]; // Turn to array
    };
    
    const words = ["a","alien","born","less","lien","never","nevertheless","new","newborn","the","zebra","zebra",];
    const compoundArr = findCompound(words);
    console.log(compoundArr);