olo
olo

Reputation: 5271

An alternative way to count a string appears in an array

I am counting how many times strings contain an aa appears in an array. I dont think there is something wrong with my code. like below

const regex_aa = /aa[^(aa)]?$/s;
let arr = [];
const sstr = ['aa', 'aaaa', 'cc', 'ccc', 'bbb', 'bbaa'];
sstr.filter(e => {
if (regex_aa.test(e)) {
  arr.push(e);
}
});

console.log(arr.length);

So the number is 3 which is correct. However, the next job is to count how many times appears, then it looks like

   const regex_aa = /aa[^(aa)]?$/s;
    const regex_bb = /bb[^(aa)]?$/s;
    let arr1 = [];
    let arr2 = [];

    const sstr = ['aa', 'aaaa', 'cc', 'ccc', 'bbb', 'bbaa'];
    sstr.filter(e => {
      if (regex_aa.test(e)) {
        arr1.push(e);
      }
      if (regex_bb.test(e)) {
        arr2.push(e);
      }
    });

    console.log(arr1.length, arr2.length);

so each time if I want to find the number of a new string, I have to create a new let, I found this way is a bit clumsy. Is there a better solution for counting strings? Thanks

Upvotes: 0

Views: 132

Answers (4)

felixmosh
felixmosh

Reputation: 35493

It is better to use Array.reduce and make is as a function.

Also, there is not need to use regex in-order to find a substring inside a string, you can use String.indexOf for that

Something like this:

const sstr = ['aa', 'aaaa', 'cc', 'ccc', 'bbb', 'bbaa'];

function countAppearanceOf(needle, arr) {
  return arr.reduce((count, item) => count + (item.indexOf(needle) > -1 ? 1 : 0), 0);
}

console.log(countAppearanceOf('aa', sstr));

Or even more generelized method, you can create a predicate method.

const sstr = ['aa', 'aaaa', 'cc', 'ccc', 'bbb', 'bbaa'];

function generalCountAppearanceOf(needle, arr, predicate) {
  return arr.reduce((count, item) => count + (predicate(needle, item) ? 1 : 0), 0);
}

function generateCounterByPredicate(predicate) {
  return (needle, arr) => generalCountAppearanceOf(needle, arr, predicate);
}

function predicatWithIndexOf(needle, item) {
  return item.indexOf(needle) > -1;
}

function predicatWithRegex(needle, item) {
  return /bb(aa)+/.test(item);
}

const countAppearanceOfWithIndexOf = generateCounterByPredicate(predicatWithIndexOf);
const countAppearanceOfWithRegex = generateCounterByPredicate(predicatWithRegex);

console.log(countAppearanceOfWithIndexOf('aa', sstr));

console.log(countAppearanceOfWithRegex('aa', sstr));

Upvotes: 1

tano
tano

Reputation: 2817

const v = 'aa';
new RegExp(v + '[^(' + v + ')]?$', 's')

Upvotes: 0

john Smith
john Smith

Reputation: 17906

You could just count up object properties

let word_count = { 
    aa: 0,
    bb: 0
 }

...

  if (regex_aa.test(e)) {
    word_count.aa += 1
  }
  if (regex_bb.test(e)) {
    word_count.bb += 1
  }

console.log(word_count) console.log(word_count.aa)

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370679

Using a regular expression here is overkill - instead, count up with .reduce by testing whether the string being iterated over .includes the substring you're looking for:

const countOccurrences = (arr, needle) => (
  arr.reduce((a, haystack) => a + haystack.includes(needle), 0)
);
console.log(countOccurrences(['aa', 'aaaa', 'cc', 'ccc', 'bbb', 'bbaa'], 'aa'));
console.log(countOccurrences(['aa', 'aaaa', 'cc', 'ccc', 'bbb', 'bbaa'], 'bb'));

Upvotes: 2

Related Questions