Counting unique words in strings
Below I am trying to pass string arrays to a function that adds unique words to an array of words, and if the word is already in the array, to increment the counter of the corresponding element in the array count:
var words = [];
var counts = [];
calculate([a, b]);
calculate([a, c]);
function calculate(result) {
for (var i = 0; i < result.length; i++) {
var check = 0;
for (var j = 0; i < tags.length; i++) {
if (result[i] == tags[j]) {
check = 1;
counts[i] = counts[i] + 20;
}
}
if (check == 0) {
tags.push(result[i]);
counts.push(20);
}
check = 0;
}
}
However, the output is obtained as follows:
words = a, b count = 2, 1
When I expect it to be: words = a, b, c count = 2,1,1
Thanks for any help in advance
source to share
Please check it out: you can check it out at: http://jsfiddle.net/knqz6ftw/
var words = [];
var counts = [];
calculate(['a', 'b']);
calculate(['a', 'c']);
calculate(['a', 'b', 'c']);
function calculate(inputs) {
for (var i = 0; i < inputs.length; i++) {
var isExist = false;
for (var j = 0; j < words.length; j++) {
if (inputs[i] == words[j]) {
isExist = true
counts[i] = counts[i] + 1;
}
}
if (!isExist) {
words.push(inputs[i]);
counts.push(1);
}
isExist = false;
}
}
console.log(words);
console.log(counts);
Output:
["a", "b", "c"] (index):46
[3, 2, 2]
source to share
Overcoming the problem in methods with good names helps you work out your logic.
Try the following:
<script type="text/javascript">
var words = [];
var counts = [];
calculate(["a", "b"]);
calculate(["a", "c"]);
console.log(words);
console.log(counts);
function calculate(result) {
for (var i=0; i<result.length; i++) {
if (array_contains(words, result[i])) {
counts[result[i]]++;
} else {
words.push(result[i]);
counts[result[i]] = 1;
}
}
}
function array_contains(array, value) {
for (var i=0; i<array.length; i++)
if (array[i] == value)
return true;
return false;
}
</script>
Output:
["a", "b", "c"]
[]
a 2
b 1
c 1
source to share
Several things were wrong, here is the working code:
var words = [];
var counts = [];
calculate(["a", "b"]);
calculate(["a", "c"]);
function calculate(result) {
for (var i = 0; i < result.length; i++) {
var check = 0;
for (var j = 0; j < words.length; j++) {
if (result[i] == words[j]) {
check = 1;
++counts[j];
}
}
if (check == 0) {
words.push(result[i]);
counts.push(1);
}
check = 0;
}
}
Jsbin: http://jsbin.com/hawaco/2/edit?js,console
Things I changed:
- Modified array literal to pass strings instead of variable names:
[a,b]
to["a","b"]
- Replaced instances of
tags
(presumably the old name) withwords
- Changed the value from 20 s 1 s
- Increased value
counts[j]
- Fixed using indexes
i
/j
Things to consider:
- Maybe it's a dictionary, not a couple of arrays:,
{"a":1, "b":2}
which will simplify the code - Pass array names to allow for other accumulators, or combine method and arrays into one object
Simplified:
var seen = {};
count(["a", "b"], seen);
count(["a", "c"], seen);
function count(words, accumulator) {
for (var i = 0; i < words.length; ++i) {
if(!accumulator.hasOwnProperty(words[i])) {
accumulator[words[i]] = 1;
} else {
++accumulator[words[i]];
}
}
}
Result:
>> seen
[object Object] {
a: 2,
b: 1,
c: 1
}
source to share
Here's my solution (using an object):
const checkWord = (str) => {
let collection = {};
// split the string into an array
let words = str.split(' ');
words.forEach((word) => {
collection[word] = word;
});
// loop again to check against the array and assign a count
for (let j = 0; j < words.length; j++) {
if (words[j] === collection[words[j]]) {
collection[words[j]] = 0;
}
collection[words[j]]++
}
console.log(collection);
};
You can also use reduce
:
const checkWord = (str) => {
let collection = {};
let words = str.split(' ');
words.forEach((word) => {
collection[word] = word;
});
for (var i = 0; i < words.length; i++) {
if (words[i] === collection[words[i]]) {
collection[words[i]] = 0;
}
}
let total = words.reduce((occurrences, word) => {
collection[word]++
return collection;
}, 0);
console.log(total);
};
source to share