How to search for words that contain all the letters from the array?

Viewed 149

I have an array of words, for example -

   const array = ["apple", "apricot", "avocado"];

I want to look for the words that contain

  1. All the letters from the array
  2. to be in order. If I'm writing -
const L = ["a", "o", "c"];
   const out = arrayF.filter ((el) => L.every ((letter) => el.includes (letter)));

Although he is looking for me all the letters, but if for example I will write-

   const L = ["a", "a", "a"];
  • This's causing me some problems.
  1. Even if I searched 3 times for the letter a he will also find me the one who has only once the letter.

  2. When I search according to -

const L = ["a", "o", "c"];

He also finds me "apricot" even if the "o" after the "c"

Regards

4 Answers

const 
  array = ["apple", "apricot", "avocado"],
  L = ["a", "o", "c"];

// iterate over array
const out = array.filter(el => {
  // initialize count to zero
  let count = 0;
  // iterate over current element's letters
  el.split('').forEach(letter => {
    // if current letter in L is letter, increment count
    if(L[count] === letter) { count++; }
  });
  // after iterating, check if all L letters were found in order
  return count === L.length;
});

console.log(out);

String.prototype.indexOf takes a second parameter, the index where to start searching.

 const search = ["a", "o", "c"];
 const target = "aoaoc";

 let targetPos = 0;

for(const searchChar of search) {
    const nextPos = target.indexOf(searchChar, targetPos );
   if (nextPos === -1) {
     return false;
   }
   targetPos = nextPos + 1;
 }

 return true;

Well, to achieve what you want I think that every() is just to simplistic for you. How about something like this:

const wordsArray = ["apple", "apricot", "avocado"];
const lettersArray = ["a", "o", "c"];

const out = wordsArray.filter(word => {
  let truncatedWord = word;
  for (const [i, letter] of lettersArray.entries()) {
    if (truncatedWord.includes(letter)) {
      if (i === lettersArray.length -1) {
        return true;
      }
      truncatedWord = truncatedWord.substr(truncatedWord.indexOf(letter) + 1)
    } else {
      return false;
    }
  }
})

Using RegExp#test() with a regular expression created from the search array. To ensure this doesn't break when special characters are included in the search array you'll need to escape the search strings before hand, here using the escape function listed on MDN.

const
  filterByHasCharsInOrder = (target, search) => {
    const regexString = search.map(s => escapeRegExp(s)).join('.*');
    const regex = new RegExp(regexString);
    // concat into array allows array or string targets to be passed
    return [].concat(target).filter(s => regex.test(s));
  },

  array = ["apple", "apricot", "avocado"];

// Testing
console.log('["a", "a", "a"]: ',
  filterByHasCharsInOrder(array, ["a", "a", "a"])
);

console.log('["a", "o", "c"]: ',
  filterByHasCharsInOrder(array, ["a", "v", "o"])
);

// pass single string
console.log('["a", "[", "o"]: ',
  filterByHasCharsInOrder("avo.ca[do", ["a", "[", "o"])
);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script>
  // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
  function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  }
</script>

Related