Adding values from objects in an array - javascript

I have an array of objects:
var array = [{
id: "cards",
amount: 5
}, {
id: "shirts",
amount: 3
}, {
id: "cards",
amount: 2
}, {
id: "shirts",
amount: 3
}]
What I need to do is loop through this array and find the total of all id types.
So in this example, I would find the total amount of cards and shirts.
I'm not sure how to do this with objects. I've tried stripping the objects down with Object.values(array), but is there a way to do it with the objects?
Thanks for your help.

This should do what you want:
var array = [
{ id: "cards", amount: 5 },
{ id: "shirts", amount: 3 },
{ id: "cards", amount: 2 },
{ id: "shirts", amount: 3 }
];
var result = array.reduce(function(entities, item) {
entities[item.id] = (entities[item.id] || 0) + item.amount;
return entities;
}, {})
console.log(result);

You would loop your array, check the id property for your target object, then enumerate and outer scope variable with the value stored in the amount property.
var totalShirts = 0;
var totalCards = 0;
for(var i = 0, len = array.length; i < len; i++){
var entry = array[i];
if(entry.id === "cards"){
totalCards += entry.amount;
}
else if(entry.id === "shirts"){
totalShirts += entry.amount;
}
}
console.log("Total Cards: " + totalCards);
console.log("Total Shirts: " + totalShirts);

Here is an example that gets the total of each item
var array = [{id:"cards", amount: 5}, {id:"shirts", amount: 3}, {id:"cards", amount: 2}, {id:"shirts", amount: 3}];
var result = array.reduce(function(accumulator, current) {
if (!(current.id in accumulator)) {
accumulator[current.id] = current.amount;
} else {
accumulator[current.id] += current.amount;
}
return accumulator;
}, {});
console.log(result);

A simple forEach will do the trick:
var counts = {}
array.forEach(v => {
counts[v.id] = (counts[v.id] || 0) + v.amount
})
console.log(counts)
will print:
{
cards: 7
shirts: 6
}

Here is a O(n) time solution.
var totals = new Object();
for(var i = 0;i < array.length;i ++) {
var id = array[i].id;
var amount = array[i].amount;
if(totals[id] == undefined) {
totals[id] = amount;
} else {
totals[id] += amount;
}
}
console.log(totals);

You can use for..of loop
var array = [{
id: "cards",
amount: 5
}, {
id: "shirts",
amount: 3
}, {
id: "cards",
amount: 2
}, {
id: "shirts",
amount: 3
}]
let res = {};
for (let {id,amount} of array) {
if (!res.hasOwnProperty(id)) res[id] = 0;
res[id] += amount;
}
console.log(res);

Use a for-loop to do this:
var totalCards = 0;
var totalShirt = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i].id === "cards") {
totalCards += arr[i].amount;
} else {
totalShirt += arr[i].amount;
}
}

Do the magic in for loop. This example should be general enough:
var array = [ {id:"cards", amount: 5}, {id:"shirts", amount: 3}, {id:"cards", amount: 2}, {id:"shirts", amount: 3} ];
var output = [];
for(var i of array) {
if(!output[i.id]) {
output[i.id] = 0;
}
output[i.id] += i.amount;
}
console.log(output);

var array = [{id:"cards", amount: 5}, {id:"shirts", amount: 3}, {id:"cards", amount: 2}, {id:"shirts", amount: 3}];
var arr = [];
array.forEach(v => arr.push(v.id));
var newArr = [...new Set(arr)];
var arr2 = [];
newArr.forEach(function(v) {
var obj = {};
obj.id = v;
obj.counter = 0;
arr2.push(obj);
});
arr2.forEach(v => array.forEach(c => c.id == v.id ? v.counter += c.amount : v));
console.log(arr2);

You can use Array.forEach() to iterate over each element of the array. The total object is an associative array where the index is the id field of array element objects.
var array = [{ id: "cards", amount: 5 },
{ id: "shirts", amount: 3 },
{ id: "cards", amount: 2},
{ id: "shirts", amount: 3 }];
var total = {};
array.forEach(function (el) {
if (total[el.id]) {
total[el.id] += el.amount
} else {
total[el.id] = el.amount
}
});
console.log(JSON.stringify(total));

You could use Array#reduce and sum the amount.
var array = [{ id: "cards", amount: 5 }, { id: "shirts", amount: 3 }, { id: "cards", amount: 2 }, { id: "shirts", amount: 3 }],
result = array.reduce(function (r, a) {
r[a.id] = (r[a.id] || 0) + a.amount;
return r;
}, {});
console.log(result);

You can use this code
if (!Object.keys) {
Object.keys = function (obj) {
var keys = [],
k;
for (k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
keys.push(k);
}
}
return keys;
};
}
then you can do this in older browsers as well:
var len = Object.keys(obj).length;

Related

merge 2 array into new array after matching their content javascript

I have 2 arrays, and I want a new array based upon condition that the content of these 2 arrays matched
arr1 = [{
package_id: 'aabbccdd',
level: 2
},
{
package_id: 'xycd21',
level: 3
}
]
arr2 = [{
package_id: 'aabbccdd',
level: 1
},
{
package_id: 'zcb21',
level: 5
}]
mergedArray = [{
package_id: 'aabbccdd',
arr1Level: 2,
arr2Level: 1
},
{
package_id: 'xycd21',
arr1Level: 3,
arr2Level: 0
},
{
package_id: 'zcb21',
arr1Level: 0,
arr2Level: 5
}]
So if package_id is to be checked in both arrays. And if found in either array, new array pushed one element where level from both array is mentioned against package_id.
I just could not figure out the logic to do that. If that can be done by lodash kindly tell me.
You can easily solve this using loops like i did here:
var arr1 = [{
package_id: 'aabbccdd',
level: 2
},
{
package_id: 'xycd21',
level: 3
}
];
var arr2 = [{
package_id: 'aabbccdd',
level: 1
},
{
package_id: 'zcb21',
level: 5
}
];
var mergedArr = [];
var tempObj = {};
for(var i = 0; i < arr1.length; i++){
tempObj.package_id = arr1[i].package_id;
tempObj.arr1Level = arr1[i].level;
tempObj.arr2Level = 0;
for(var k = 0; k < arr2.length; k++){
if(arr1[i].package_id === arr2[k].package_id){
tempObj.arr2Level = arr2[k].level;
}
}
mergedArr.push(tempObj);
tempObj = {};
}
for(i = 0; i < arr2.length; i++){
var isNew = true;
for(k = 0; k < mergedArr.length; k++){
if(arr2[i].package_id === mergedArr[k].package_id){
isNew = false;
}
}
if(isNew){
tempObj.package_id = arr2[i].package_id;
tempObj.arr2Level = arr2[i].level;
tempObj.arr1Level = 0;
mergedArr.push(tempObj);
tempObj = {};
}
}
console.log(mergedArr);
You can first add both arrays to one array and then use reduce() and forEach() to create new array of objects. Also you can use another object to group elements by package_id
var arr1 = [{ package_id: 'aabbccdd', level: 2 }, { package_id: 'xycd21', level: 3 }];
var arr2 = [{ package_id: 'aabbccdd', level: 1 }, { package_id: 'zcb21', level: 5 }];
var o = {}
var arrays = [arr1, arr2]
var keys = Array.from(Array(arrays.length), (e, i) => ({['arr' + (i + 1) + 'Level']: 0}))
var result = arrays.reduce(function(r, a, i) {
a.forEach(function(e) {
if (!o[e.package_id]) {
o[e.package_id] = Object.assign({}, {package_id: e.package_id}, ...keys)
r.push(o[e.package_id]);
}
o[e.package_id]['arr' + (i + 1) + 'Level'] = e.level;
})
return r;
}, [])
console.log(result)
You could use a structure approach with dynamic keys for different arrays and use the keys as help for generating default values.
var arr1 = [{ package_id: 'aabbccdd', level: 2 }, { package_id: 'xycd21', level: 3 }],
arr2 = [{ package_id: 'aabbccdd', level: 1 }, { package_id: 'zcb21', level: 5 }],
keys = [{ level: 'arr1level' }, { level: 'arr2level' }],
result = [arr1, arr2].reduce(function (hash) {
return function (r, a, i) {
a.forEach(function (b) {
if (!hash[b.package_id]) {
hash[b.package_id] = { package_id: b.package_id },
r.push(hash[b.package_id]);
}
keys.forEach(function (key) {
Object.keys(key).forEach(function (k) {
hash[b.package_id][key[k]] = 0;
});
});
Object.keys(b).forEach(function (k) {
var key = keys[i][k] || k;
hash[b.package_id][key] = b[k];
});
});
return r;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Get all the objects from a list

So, I have something like this:
objArray1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}];
objArray2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }];
I am trying to use javascript to make an array with all the candidates and see how many votes each of them have. The part to calculate the votes is easy, but I don't know how to put all the candidates in one array.
I should get an array with: Alex, Paul, Ben and Melisa.
Thank you!
You could use a hashtable and group by name.
var array1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}],
array2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }],
grouped = [array1, array2].reduce(function (hash) {
return function (r, a) {
a.forEach(function (o, i) {
var name = o['candidate' + (i + 1)];
if (!hash[name]) {
hash[name] = { candidate: name, votes: 0 };
r.push(hash[name]);
}
hash[name].votes += o.votes;
});
return r;
};
}(Object.create(null)), []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var candidates = [];
var found = 0;
for(var i=0;objArray1.length>i;i++){
found = 0;
//add votes to candidate array
for(var j=0;candidates.length>j;j++){
if(candidates[j].name==objArray1[i][Object.keys(objArray1[i])[0]]){
candidates[j].votes = candidates[j].votes+objArray1[i].votes;
found = 1;
}
}
//if condidate not found in votes array, create new
if(found==0){
var tmp = {};
tmp.name = objArray1[i].candidate;
tmp.votes = objArray1[i].votes;
//add to array
candidates.push(tmp);
}
}
console.log(candidates);
Generate an object which holds property name as name and vote count as value.
var objArray1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}], objArray2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }];
var res = []
// cobine two arrays
.concat(objArray1, objArray2)
// iterate over the arrays
.reduce(function(obj, o) {
// get the key except the votes
var key = Object.keys(o).find(function(k) {
return k != 'votes';
})
// define property if not already defined
obj[key] = obj[key] || 0;
// add the vote count
obj[key] += o.votes;
// return object refernece
return obj;
// set initial value as empty object
}, {});
console.log(res);
// get the names array if need
console.log(Object.keys(res));
Short solution using Array.prototype.concat(), Array.prototype.reduce() and Array.prototype.map() functions:
var objArray1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}],
objArray2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }],
grouped = objArray1.concat(objArray2).reduce(function(r, o){
var k = Object.keys(o).filter(function(k){
return k.indexOf('candidate') === 0;
})[0];
(r[o[k]])? r[o[k]].votes += o.votes : r[o[k]] = {candidate: o[k], votes: o.votes};
return r;
}, {}),
result = Object.keys(grouped).map(function(k){ return grouped[k]; });
console.log(result);
To get the list of names as you asked
var rawArrays = objArray1.concat(objArray2), Candidates = [], tmp = []
for (var i in rawArrays) {
tmp[rawArrays[i][Object.keys(rawArrays[i])[0]]] = 1
}
Candidates = Object.keys(tmp)
To get array with candidates and votes sum
var rawArrays = objArray1.concat(objArray2), Candidates = []
for (var i in rawArrays) {
name = rawArrays[i][Object.keys(rawArrays[i])[0]]
if (Candidates[name]) Candidates[name] += rawArrays[i].votes
else Candidates[name] = rawArrays[i].votes
}

Create object from a property in an array of objects

I have an array of objects like this:
[
{id: 'id1', random: 'labels.prop1'},
{id: 'id2', random: 'labels.prop2'},
{id: 'id3', random: 'texts.anotherprop'}
]
Is there a short way to generate from that array an object based on the property random? I'd need this:
{
texts: {
anotherprop: ''
},
labels: {
prop1: '',
prop2: ''
}
}
You can use reduce() two times to build this nested object.
var data = [
{id: 'id1', random: 'labels.prop1'},
{id: 'id2', random: 'labels.prop2'},
{id: 'id3', random: 'texts.anotherprop'}
]
var result = data.reduce(function(r, o) {
var arr = o.random.split('.')
arr.reduce(function(a, b, i) {
return (i != arr.length - 1) ? a[b] || (a[b] = {}) : a[b] = ''
}, r)
return r;
}, {})
console.log(result)
You could iterate the array and build an object based on the parts of random.
function setValue(object, path, value) {
var fullPath = path.split('.'),
way = fullPath.slice(),
last = way.pop();
way.reduce(function (r, a) {
return r[a] = r[a] || {};
}, object)[last] = value;
}
var data = [{ id: 'id1', random: 'labels.prop1' }, { id: 'id2', random: 'labels.prop2' }, { id: 'id3', random: 'texts.anotherprop' }],
result = {};
data.forEach(function (o) {
setValue(result, o.random, '');
});
console.log(result);
var arr = [
{id: 'id1', random: 'labels.prop1'},
{id: 'id2', random: 'labels.prop2'},
{id: 'id3', random: 'texts.anotherprop'}
];
var result = {};
arr.forEach(function(o) {
var parts = o.random.split('.');
var r = result;
var i = 0;
for( ; i < parts.length - 1; i++) {
r[parts[i]] = r[parts[i]] || {};
r = r[parts[i]];
}
r[parts[i]] = '';
});
console.log(result);

Merge arrays in JS

Suppose I have the following arrays:
var first = [
{ id: 1, name: 'first' },
{ id: 2, name: 'second' },
{ id: 3, name: 'third' }
]
var second = [
{ id: 2, field: 'foo2' },
{ id: 3, field: 'foo3' },
{ id: 4, field: 'foo4' }
]
var third = [
{ id: 2, data: 'some2' },
{ id: 5, data: 'some5' },
{ id: 6, data: 'some6' }
]
I want to merge them to get the following result:
var result = [
{ id: 1, name: 'first', field: undefined, data: undefined },
{ id: 2, name: 'second', field: 'foo2', data: 'some2' },
{ id: 3, name: 'third', field: 'foo3', data: undefined },
{ id: 4, name: undefined, field: 'foo4', data: undefined },
{ id: 5, name: undefined, field: undefined, data: 'some5' },
{ id: 6, name: undefined, field: undefined, data: 'some6' }
]
How could I do it with JavaScript?
You should get all existed keys and after create new Objects with fill "empty" keys:
function mergeArrays(){
var keys = {};
//save all existed keys
for(var i=arguments.length;--i;){
for(var j=arguments[i].length;--j;){
for(var key in arguments[i][j]){
keys[key] = true;
}
}
}
var res = [];
for(var i=arguments.length;--i;){
for(var j=arguments[i].length;--j;){
//set clone of object
var clone = JSON.parse(JSON.stringify(arguments[i][j]));
for(var key in keys){
if(!(key in clone)){
clone[key] = undefined;
}
}
res.push(clone);
}
}
return res;
}
https://jsfiddle.net/x3b0tk3g/
There is no simple solution for what you want. Here is my suggestion.
var first = [
{ id: 1, name: 'first' },
{ id: 2, name: 'second' },
{ id: 3, name: 'third' }
]
var second = [
{ id: 2, filed: 'foo2' },
{ id: 3, field: 'foo3' },
{ id: 4, field: 'foo4' }
];
var third = [
{ id: 2, data: 'some2' },
{ id: 4, data: 'some4' },
{ id: 6, data: 'some6' }
];
var result = {};
first.concat(second,third).forEach(function(item){
var id = item.id;
var row = result[id];
if(!row){
result[id] = item;
return;
}
for(var column in item){
row[column] = item[column];
}
});
var finalResult = Object.keys(result).map(function(id){
return result[id];
});
console.log(finalResult);
fiddle: http://jsfiddle.net/bs20jvnj/2/
function getByProperty(arr, propName, propValue) {
for (var i = 0; i < arr.length; i++) {
if (arr[i][propName] == propValue) return arr[i];
}
}
var limit = first.length + second.length + third.length;
var res = [];
for (var i = 1; i < limit; i++) {
var x = $.extend({}, getByProperty(first, "id", i), getByProperty(second, "id", i), getByProperty(third, "id", i));
console.log(x["id"]);
if (x["id"] === undefined) x["id"] = i;
res.push(x);
}
console.log(res);
There's probably a shorter way to solve this, but this covers all the steps, including ensuring that there are default properties that are undefined if not found. It also takes any number of input arrays, and you can specify what default keys you require if they're not already covered by the keys in the existing objects, so pretty future-proof for your needs.
// merges the key/values of two objects
function merge(a, b) {
var key;
if (a && b) {
for (key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
}
return a;
}
function concatenate() {
var result = [];
var args = arguments[0];
for (var i = 0, l = args.length; i < l; i++) {
result = result.concat(args[i]);
}
return result;
}
// return a default object
function getDefault() {
return {
id: undefined,
name: undefined,
data: undefined,
field: undefined
};
}
// loop over the array and check the id. Add the id as a key to
// a temporary pre-filled default object if the key
// doesn't exist, otherwise merge the existing object and the
// new object
function createMergedArray(result) {
var temp = {};
var out = [];
for (var i = 0, l = result.length; i < l; i++) {
var id = result[i].id;
if (!temp[id]) temp[id] = getDefault();
merge(temp[id], result[i]);
}
// loop over the temporary object pushing the values
// into an output array, and return the array
for (var p in temp) {
out.push(temp[p]);
}
return out;
}
function mergeAll() {
// first concatenate the objects into a single array
// and then return the results of merging that array
return createMergedArray(concatenate(arguments));
}
mergeAll(first, second, third);
DEMO

Idiomatically find the number of occurrences a given value has in an array

I have an array with repeating values. I would like to find the number of occurrences for any given value.
For example, if I have an array defined as so: var dataset = [2,2,4,2,6,4,7,8];, I want to find the number of occurrences of a certain value in the array. That is, the program should show that if I have 3 occurrences of the value 2, 1 occurrence of the value 6, and so on.
What's the most idiomatic/elegant way to do this?
reduce is more appropriate here than filter as it doesn't build a temporary array just for counting.
var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var count = dataset.reduce(function(n, val) {
return n + (val === search);
}, 0);
console.log(count);
In ES6:
let count = dataset.reduce((n, x) => n + (x === search), 0);
Note that it's easy to extend that to use a custom matching predicate, for example, to count objects that have a specific property:
people = [
{name: 'Mary', gender: 'girl'},
{name: 'Paul', gender: 'boy'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
]
var numBoys = people.reduce(function (n, person) {
return n + (person.gender == 'boy');
}, 0);
console.log(numBoys);
Counting all items, that is, making an object like {x:count of xs} is complicated in javascript, because object keys can only be strings, so you can't reliably count an array with mixed types. Still, the following simple solution will work well in most cases:
count = function (ary, classifier) {
classifier = classifier || String;
return ary.reduce(function (counter, item) {
var p = classifier(item);
counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
return counter;
}, {})
};
people = [
{name: 'Mary', gender: 'girl'},
{name: 'Paul', gender: 'boy'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
];
// If you don't provide a `classifier` this simply counts different elements:
cc = count([1, 2, 2, 2, 3, 1]);
console.log(cc);
// With a `classifier` you can group elements by specific property:
countByGender = count(people, function (item) {
return item.gender
});
console.log(countByGender);
2017 update
In ES6, you use the Map object to reliably count objects of arbitrary types.
class Counter extends Map {
constructor(iter, key=null) {
super();
this.key = key || (x => x);
for (let x of iter) {
this.add(x);
}
}
add(x) {
x = this.key(x);
this.set(x, (this.get(x) || 0) + 1);
}
}
// again, with no classifier just count distinct elements
results = new Counter([1, 2, 3, 1, 2, 3, 1, 2, 2]);
for (let [number, times] of results.entries())
console.log('%s occurs %s times', number, times);
// counting objects
people = [
{name: 'Mary', gender: 'girl'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
];
chessChampions = {
2010: people[0],
2012: people[0],
2013: people[2],
2014: people[0],
2015: people[2],
};
results = new Counter(Object.values(chessChampions));
for (let [person, times] of results.entries())
console.log('%s won %s times', person.name, times);
// you can also provide a classifier as in the above
byGender = new Counter(people, x => x.gender);
for (let g of ['boy', 'girl'])
console.log("there are %s %ss", byGender.get(g), g);
A type-aware implementation of Counter can look like this (Typescript):
type CounterKey = string | boolean | number;
interface CounterKeyFunc<T> {
(item: T): CounterKey;
}
class Counter<T> extends Map<CounterKey, number> {
key: CounterKeyFunc<T>;
constructor(items: Iterable<T>, key: CounterKeyFunc<T>) {
super();
this.key = key;
for (let it of items) {
this.add(it);
}
}
add(it: T) {
let k = this.key(it);
this.set(k, (this.get(k) || 0) + 1);
}
}
// example:
interface Person {
name: string;
gender: string;
}
let people: Person[] = [
{name: 'Mary', gender: 'girl'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
];
let byGender = new Counter(people, (p: Person) => p.gender);
for (let g of ['boy', 'girl'])
console.log("there are %s %ss", byGender.get(g), g);
array.filter(c => c === searchvalue).length;
Here is one way to show ALL counts at once:
var dataset = [2, 2, 4, 2, 6, 4, 7, 8];
var counts = {}, i, value;
for (i = 0; i < dataset.length; i++) {
value = dataset[i];
if (typeof counts[value] === "undefined") {
counts[value] = 1;
} else {
counts[value]++;
}
}
console.log(counts);
// Object {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
//}
Newer browsers only due to using Array.filter
var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var occurrences = dataset.filter(function(val) {
return val === search;
}).length;
console.log(occurrences); // 3
const dataset = [2,2,4,2,6,4,7,8];
const count = {};
dataset.forEach((el) => {
count[el] = count[el] + 1 || 1
});
console.log(count)
// {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
// }
Using a normal loop, you can find the occurrences consistently and reliably:
const dataset = [2,2,4,2,6,4,7,8];
function getNumMatches(array, valToFind) {
let numMatches = 0;
for (let i = 0, j = array.length; i < j; i += 1) {
if (array[i] === valToFind) {
numMatches += 1;
}
}
return numMatches;
}
alert(getNumMatches(dataset, 2)); // should alert 3
DEMO: https://jsfiddle.net/a7q9k4uu/
To make it more generic, the function could accept a predicate function with custom logic (returning true/false) which would determine the final count. For example:
const dataset = [2,2,4,2,6,4,7,8];
function getNumMatches(array, predicate) {
let numMatches = 0;
for (let i = 0, j = array.length; i < j; i += 1) {
const current = array[i];
if (predicate(current) === true) {
numMatches += 1;
}
}
return numMatches;
}
const numFound = getNumMatches(dataset, (item) => {
return item === 2;
});
alert(numFound); // should alert 3
DEMO: https://jsfiddle.net/57en9nar/1/
You can count all items in an array, in a single line, using reduce.
[].reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
This will yield an object, whose keys are the distinct elements in the array and values are the count of occurences of elements in the array. You can then access one or more of the counts by accessing a corresponding key on the object.
For example if you were to wrap the above in a function called count():
function count(arr) {
return arr.reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
}
count(['example']) // { example: 1 }
count([2,2,4,2,6,4,7,8])[2] // 3
You can do with use of array.reduce(callback[, initialValue]) method in JavaScript 1.8
var dataset = [2,2,4,2,6,4,7,8],
dataWithCount = dataset.reduce( function( o , v ) {
if ( ! o[ v ] ) {
o[ v ] = 1 ;
} else {
o[ v ] = o[ v ] + 1;
}
return o ;
}, {} );
// print data with count.
for( var i in dataWithCount ){
console.log( i + 'occured ' + dataWithCount[i] + 'times ' );
}
// find one number
var search = 2,
count = dataWithCount[ search ] || 0;
I've found it more useful to end up with a list of objects with a key for what is being counted and a key for the count:
const data = [2,2,4,2,6,4,7,8]
let counted = []
for (var c of data) {
const alreadyCounted = counted.map(c => c.name)
if (alreadyCounted.includes(c)) {
counted[alreadyCounted.indexOf(c)].count += 1
} else {
counted.push({ 'name': c, 'count': 1})
}
}
console.log(counted)
which returns:
[ { name: 2, count: 3 },
{ name: 4, count: 2 },
{ name: 6, count: 1 },
{ name: 7, count: 1 },
{ name: 8, count: 1 } ]
It isn't the cleanest method, and if anyone knows how to achieve the same result with reduce let me know. However, it does produce a result that's fairly easy to work with.
First, you can go with Brute Force Solution by going with Linear Search.
public int LinearSearchcount(int[] A, int data){
int count=0;
for(int i=0;i<A.length;i++) {
if(A[i]==data) count++;
}
return count;
}
However, for going with this, we get Time complexity as O(n).But by going with Binary search, we can improve our Complexity.
If you try to do it this way, you might get an error like the one below.
array.reduce((acc, arr) => acc + (arr.label === 'foo'), 0); // Operator '+' cannot be applied to type 'boolean'.
One solution would be to do it this way
array = [
{ id: 1, label: 'foo' },
{ id: 2, label: 'bar' },
{ id: 3, label: 'foo' },
{ id: 4, label: 'bar' },
{ id: 5, label: 'foo' }
]
array.reduce((acc, arr) => acc + (arr.label === 'foo' ? 1 : 0), 0); // result: 3

Categories