I am taking the LeetCode challenge 819. Most Common Word:
Given a string
paragraph
and a string array of the banned wordsbanned
, return the most frequent word that is not banned. It is guaranteed there is at least one word that is not banned, and that the answer is unique.The words in
paragraph
are case-insensitive and the answer should be returned in lowercase.Example 1
Input:
paragraph = "Bob hit a ball, the hit BALL flew far after it was hit."
,banned = ["hit"]
Output:"ball"
This is my code:
var mostCommonWord = function(paragraph, banned) {
let words = paragraph.toLowerCase().split(" ");
let unbannedwords = words.filter((word)=> word !== banned[0] );
let map = {};
console.log(unbannedwords)
for (let i = 0; i < unbannedwords.length; i ) {
count = 0;
for (let j = i 1; j < unbannedwords.length; j ) {
if (unbannedwords[i] === unbannedwords[j]) {
count ;
map[unbannedwords[i]] = count;
}
}
}
console.log(map)
let obj = Object.values(map)
let max = Math.max(...obj);
function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}
return getKeyByValue(map, max);
};
Output console.log
:
[
'bob', 'a',
'ball', 'the',
'ball', 'flew',
'far', 'after',
'it', 'was'
]
{ }
I don't why properties are not being from the loop in map
object?
CodePudding user response:
The problem is that the split(" ")
call will leave the punctuation in, so you'll have both "ball," and "ball" in the resulting array. Obviously this will make your code miss some equalities.
To resolve this, change this line:
let words = paragraph.toLowerCase().split(" ");
to:
let words = paragraph.toLowerCase().match(/\w /g);
A second issue occurs with how you set the map
values. Currently, you are resetting the count when a word is encountered the second time in the outer loop. Then the first encounter will no longer play a role. Also, the map
will only register words when they occur at least 2 times (once in outer loop, once in inner loop).
You should make sure to set map[unbannedwords[i]]
even when there is no next occurrence. The advantage of the map should be that you don't need the second loop, but that the first loop will find the entry in the map and just increment it with one if it already existed.
You'll still have some other things to do, as currently your code is only taking the first banned word into account, i.e. banned[0]
. In an edit to the question you propose to use replaceAll(banned, "")
, but that is not how replaceAll
works. It expects its first argument to be a string or regular expression. Since you pass it an array, the array is turned into one single, comma-joined string, which is unlikely to match anything.
Here is a spoiler solution:
var mostCommonWord = function(paragraph, banned) { const words = paragraph.toLowerCase() .match(/\w /g) .filter(word => !banned.includes(word)) const count = {}; for (const word of words) count[word] = (count[word] ?? 0) 1; const maxCount = Math.max(...Object.values(count)); return Object.keys(count).find(word => count[word] == maxCount); };