Reputation: 726
I am trying to count occurrences of each word in longer text using the match
method, but instead of result
I get only an error:
Cannot read property 'length' of null
My function looks like this:
const myText = "cat dog stop rain cat"
myText.split(" ").forEach((word) => {
const numberOfOccurrences = myText.match(/word/g).length
console.log(`${word} - ${numberOfOccurrences}`)
})
How can I repair it to get the proper result?
Upvotes: 1
Views: 11455
Reputation: 166
I agree with above answer but if in case you looking with array of strings this will do
var textArr = ['apple', 'mango' ,'apple', 'apple' ,'cherry'];
var arr = [...new Set(textArr)];
arr.forEach(v => console.log(`${v} appears: ${textArr.filter(c => c == v).length} times`));
Upvotes: 0
Reputation: 57944
The regular expression is literally matching word
, as variable word
is never indicated. There is no match found in the string myText
so it's null, hence the error. Try like this:
myText.match(new RegExp(word, "g")).length
This uses the RegExp
constructor, which takes in two arguments: the pattern and the flags. The above will pass the actual value of word
instead of the literal word
, and the flag g
. It's equivalent to /word/g
except word
is correctly matched to what word
is passed. See the following snippet:
const myText = "cat dog stop rain cat"
myText.split(" ").forEach((word) => {
const numberOfOccurrences = myText.match(new RegExp(word, "g")).length
console.log(`${word} - ${numberOfOccurrences}`)
})
As others have pointed out, there are better ways to do this. The output of your code above outputs the occurrence of cat
twice, because it occurs twice. I would recommend saving your counts in an object and updating the counts at each pass, which ibrahim mahrir shows in their answer. The idea is to use reduce
to iterate over the split array, and reduce with the initial value of an empty object. Then, the empty object is updated with the counts of the word added by one, with initial count of zero.
Upvotes: 8
Reputation: 1034
I think your example is just trying to match the literal word
. You should use RegExp(word, "gi"
instead.
const myText = "cat dog stop rain cat"
myText.split(" ").forEach((word) => {
const numberOfOccurrences = myText.match(RegExp(word, "gi")).length
console.log(`${word} - ${numberOfOccurrences}`)
})
Upvotes: 0
Reputation: 3608
Your expression returns an array, which has one entry, hence it always returns 1. You also have to create a regexp from the word because match takes a regexp and not a string as its argument.
Try this instead
const myText = "cat dog stop word rain cat"
myText.split(" ").forEach((word) => {
const numberOfOccurrences = myText.match(new RegExp(word, 'g')).length;
console.log(`${word} - ${numberOfOccurrences}`)
})
Upvotes: 0
Reputation: 41893
You can also try simple solution with Array#filter
, without using RegExp
and Array#match
.
var text = "cat dog stop rain cat";
var textArr = text.split(' ');
var arr = [...new Set(text.split(' '))];
arr.forEach(v => console.log(`${v} appears: ${textArr.filter(c => c == v).length} times`));
Upvotes: 1
Reputation: 31682
It's because nothing is matched. There is no word word
in your string. Try this:
const myText = "cat dog stop rain cat"
myText.split(" ").forEach((word) => {
const numberOfOccurrences = myText.match(new RegExp(word, 'g')).length;
console.log(`${word} - ${numberOfOccurrences}`)
})
Without regular expressions:
Use a hash object like this:
const myText = "cat dog stop rain cat"
var result = myText.split(" ").reduce((hash, word) => {
hash[word] = hash[word] || 0;
hash[word]++;
return hash;
}, {});
console.log(result);
Upvotes: 0