Here is an alternative method utilizing function generators.
While there may not be a clear advantage to using this approach over others, it does offer more flexibility in controlling the entire process.
It's worth noting that the string is only traversed once, so the overall iteration cycle should be relatively quick.
The code provides an object as output, with each key representing a character and its respective occurrence count based on the specified search criteria.
If no array of searched characters is provided, the calc_fit function automatically generates one, capturing occurrences of uppercase and lowercase letters, punctuation, and symbols separately. However, this can be easily customized.
// Function that iterates through a string and yields the current character if it matches the specified list of characters.
function* matchChars(s, chars) {
for (var char of s) {
if (chars.indexOf(char) > -1) yield { char: char };
}
}
// The function name in the original code may seem odd, but it's the OP's choice.
function calc_fit(element, chars) {
chars = chars || [...new Set(element)];
// Create an object from the array, initializing all counts to zero.
const matchList = chars.reduce((acc, next) => (acc[next] = 0, acc), {});
// Iterate through all matches and increment the counts in matchList.
for (var match of matchChars(element, chars)) matchList[match.char]++;
// Return the final matchList.
return matchList;
}
// Assertions: should match all specified characters.
console.log(calc_fit('element', ["e", "l", "m", "n", "t"]));
// Assertions: should return all zeros.
console.log(calc_fit('', ["e", "l", "m", "n", "t"]));
// Assertions: should automatically detect characters, including upper and lower case.
console.log(calc_fit('hello, world. ThIs is beatiful!'));