Looping through a list of arrays to count the objects - javascript

I am been having trouble counting the number of objects in this array in javascript.
Below is the array of objects i try to count with my code.
<script>
var arr = [
{"gateways":["ccu1"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_cam","ip_other"]},
{"gateways":["v3"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_cam"]},
{"gateways":["v2","v3","v4","ccu2"],"manufacturer":["homematic","intertechno"],"ir":["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["v2","ccu1","ccu2"],"manufacturer":["homematic"],"ir":["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["gw_none"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_cam"]},
{"gateways":["v3","ccu2"],"manufacturer":["homematic","fs20","intertechno","elro","Eltako Enocean"],"ir":["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["v3","v4"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_other"]},
{"gateways":["v3","v4"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_other"]},
{"gateways":["v2"],"manufacturer":["intertechno"],"ir":["ir_yes"],"ip":["ip_other"]}
];
var counter = [];
for(var i=0; i<arr.length; i++) {
//console.log(arr[i]);
for(var index in arr[i]) {
console.log(index);
if(counter[index] === undefined) {
counter[index] = [];
}
}
}
console.log(counter);
</script>
I want the number of the objects to push into the empty array "counter" when you console log "counter" e.g.
gateways
ccu2 42
v4 70
v2 95
v3 91
v4plus 32
ccu1 16
gw_none 10
ip
ip_cam 4
ip_other 10
ip_none 4
ir
ir_yes 13
ir_no 18
manufacturer
homematic 24
fs20 59
intertechno 38
elro 63
homeeasy 40
somfy 11
I am new to programming and trying my hands on some few exercises like this one but i got stuck. I'm left with the codes to put the object counter to the empty array. I have tried but cannot let it work. I would appreciate any help and i hope my assignment makes sense and is understandable.

Change this:
if(counter[index] === undefined) {
counter[index] = [];
}
To this:
if(counter[index] === undefined) {
counter[index] = [];
}
counter[index].push( arr[i][index] );

Hope this code is helpful.
var arr = [
{"gateways":["ccu1"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_cam","ip_other"]},
{"gateways":["v3"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_cam"]},
{"gateways":["v2","v3","v4","ccu2"],"manufacturer":["homematic","intertechno"],"ir":["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["v2","ccu1","ccu2"],"manufacturer":["homematic"],"ir":["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["gw_none"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_cam"]},
{"gateways":["v3","ccu2"],"manufacturer":["homematic","fs20","intertechno","elro","Eltako Enocean"],"ir":["ir_yes"],"ip":["ip_cam","ip_other"]},
{"gateways":["v3","v4"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_other"]},
{"gateways":["v3","v4"],"manufacturer":["homematic"],"ir":["ir_no"],"ip":["ip_other"]},
{"gateways":["v2"],"manufacturer":["intertechno"],"ir":["ir_yes"],"ip":["ip_other"]}
];
var types = Object.keys(arr[0]); //Returns ["gateways","manufacturer","ir","ip"]
var counter = {};
types.forEach(function(type){
var values = [].concat.apply([], arr.map(function(d){ return d[type] })); // Find all values for each key like gateways
//Count occurrence of each value
var counts = {};
for(var i = 0; i< values.length; i++) {
var num = values[i];
counts[num] = counts[num] ? counts[num]+1 : 1;
}
counter[type] = counts;
});
alert(JSON.stringify(counter));
Output Obtained:
{
"gateways": {
"ccu1": 2,
"v3": 5,
"v2": 3,
"v4": 3,
"ccu2": 3,
"gw_none": 1
},
"manufacturer": {
"homematic": 8,
"intertechno": 3,
"fs20": 1,
"elro": 1,
"Eltako Enocean": 1
},
"ir": {
"ir_no": 5,
"ir_yes": 4
},
"ip": {
"ip_cam": 6,
"ip_other": 7
}
}

Thanks guys but i sat down and thought i got what i was missing;
//first we initialised counter
var counter = [];
//we then loop over the big array
for(var i=0; i<arr.length; i++) {
//we save then the single objects
var obj = arr[i];
// We then evaluate Object -> looping and count on each entry
for(var key in obj) {
//check whether there is already an entry for the respective
//index (gateways, Manufacturer etc)
if(counter[key] === undefined) {
counter[key] = [];
}
//Save the individual array of Object entries
var arr2 = obj[key];
//Looping and counting the array
for(var k=0; k<arr2.length; k++) {
var entry = arr2[k];
//Check whether there is already a counter for that
//item
if(counter[key][entry] === undefined) {
counter[key][entry] = 1;
} else {
counter[key][entry]++;
}
}
}
}
console.log(counter);

Related

Javascript - Adding multiple values to keys

I am trying to find the places of each letter in a sentence by using "dictionaries". The problem is I want to find all the places that each letter is and not only the last one. I am very new to JavaScript and couldn't figure out the way to do it.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ )
if (!stringArgument[i] in dict){
dict[stringArgument[i]] = [];
}else{
dict[stringArgument[i]] = [i+1]
}
return dict
}
var a = letters('Lost time is never found again.');
console.log(a);
naturally gives this output:
{ L: [ 1 ], o: [ 17 ], s: [ 10 ], t: [ 5 ]...
but it should give this:
{ L: [ 1 ], o: [ 2, 17 ], s: [ 3, 10 ], t: [ 4, 5 ]...
Also each letter is saved to the dictionary at the same order they appear in the sentence, how can I order the letters alphabetically?
What you need is a function that gets the positions of a character in a given string.
Try this:
function findAllPositions(char, content) {
var result = [];
let index = content.indexOf(char);
while(index !== -1) {
result.push(index);
index = content.indexOf(char, index + 1);
}
return result;
}
findAllPositions('o', 'Lost time is never found again.'); // Result =  [1, 20]
Using this we can update the letter function as follows:
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (const char of stringArgument) {
dict[char] = findAllPositions(char, stringArgument)
}
return dict;
}
letters('is again.')
/*
{
"i": [0, 5],
"s": [1],
"a": [2, 4],
"g": [3],
"n": [6],
".": [7]
}
*/
You need to have
parantheses for the check
if (!(stringArgument[i] in dict)) {
create an array if the above is true
push the postion to the array
For getting a sorted output, you could take the entries of the object, apply a sorting by taking the key and show the result in order.
Object have an insertation oder for not positive 32 bit numbers (like indixes) or symbols. The index like numbers are sorted by value and appears first in the object.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
if (!(stringArgument[i] in dict)) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters('Lost time is never found again.');
Object
.entries(a)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([key, positions]) => console.log(key, ...positions));
console.log(a);
First, for any item, if it is not in an empty array:
var notInDict = !(stringArgument[i] in dict);
If not in dict, then initialize an empty array and push the item in it using
dict[stringArgument[i]].push(i + 1);
Try this.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, "");
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
var notInDict = !(stringArgument[i] in dict);
if (notInDict) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters("Lost time is never found again.");
console.log(a);
you are assigning a new array at each iteration
dict[stringArgument[i]] = [i+1]
what you need to do is push the new position to existing array.
dict[stringArgument[i]].push(i+1)
also, remove the else block
function letters(stringArgument) {
stringArgument = stringArgument.toLowerCase().replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ ){
if (!dict.hasOwnProperty(stringArgument[i])){
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i+1);
}
//sorting
var letters = Object.keys(dict); //returns a array
letters.sort();
var sortedDic = {};
for(var i in letters) {
sortedDic[letters[i]] = dict[letters[i]];
}
return sortedDic;
}
var a = letters('Lost time is never found again.');
console.log(a);
for the first part you can also do that:
let sentence = 'Lost time is never found again.'
let tabLetters = [...sentence.replace(/ /g,'')].reduce((a,c,i)=>
{
if (!a[c]) a[c] = [i+1]
else a[c].push(i+1)
return a
},{})
document.write(JSON.stringify(tabLetters))

Matching 3 or more same elements in a array and adding them to a list

I am trying to find 3 or more matching items in array but it is only matching the first 3 and none matching for the rest of the array. If anyone could help would be great :)
var grid = [2,2,2,5,5,5,3,3,3,3];
checkResults();
function checkResults(){
var list_matches = []; // store all matches found
var listcurrent = []; // store current
var maxitems = 3;
var last = -1; // last cell
for(let j =0; j < grid.length; ++j){
let item = grid[j];
// check if last is null
if(last == -1){
// add first item
listcurrent.push(item);
last = item;
console.log("Added: "+item);
continue;
}
let wasMatch = false;
// check match
if(item == last){
wasMatch = true;
listcurrent.push(item);
last = item;
console.log("Added Match: "+item);
}
if(!wasMatch){
console.log("Not matched: " + item);
if(listcurrent.length >= maxitems){
list_matches.push(listcurrent);
}
// reset to null
last = -1;
listcurrent = [];
}
}
console.log(list_matches);
console.log("Cols: " + grid.length);
}
Expected Results: from [2,2,2,5,5,5,3,3,3,3];
0: 222
1: 555
2: 3333
Current output is:
0: 222 and thats it
You could take a temporary array for collecting the same values and push this array if the length has the wanted minimum length.
function getMore(array, min) {
var result = [],
temp;
array.forEach((v, i, a) => {
if (v !== a[i - 1]) return temp = [v];
temp.push(v);
if (temp.length === min) result.push(temp);
});
return result;
}
console.log(getMore([2, 2, 2, 5, 5, 5, 3, 3, 3, 3], 3));
you can do something like this:
var grid = [ 1, 1, 2, 3, 4, 5 ];
var hashMap = {};
for( var i = 0; i < grid.length; i++ ) {
if( hashMap.hasOwnProperty( grid[i] ) ) {
hashMap[ grid[i] ]++;
} else {
hashMap[ grid[i] ] = 1;
}
}
it will helps you.
//toLowerCase for get unique on words, not on character. if i ignore this, it will return two words=> developers. and developers
//first Split and join for remove '.' character form text and finally last split is for convert string to an Array of words that splited by Space character
let uniqWords = Array.from(new Set(text));
//using Set to get unique words and convert it to Array to do more on Array.
let count = {};
// declare varriable for store counts of words.
uniqWords.map(item => {
count[item] = text.filter(elem => {
//create property with the name of words and filter common words to an Array
return elem == item
}).length
//get Array length for get words repeated count.
})
console.table(count)
//log Result into Console
Another solution using Array.prototype[reduce/map/filter]
const someArray = [2, 2, 2, 5, 5, 5, 3, 3, 3, 3, 9, 9];
console.log(aggregate(someArray));
function aggregate(arr) {
return arr
// retrieve unique values
.reduce((acc, val) => !acc.includes(val) && acc.concat(val) || acc, [])
// use unique values to map arr values to strings
// if number of matches >= 3
.map(val => {
const filtered = arr.filter(v => v == val);
return filtered.length > 2 ? filtered.join("") : false
})
// filter non falsy values
.filter(val => val);
}

JavaScript - count occurrence of strings

I'm looking to count the occurances of certain strings within JSON - in this instance sensorUUID.
var newDataArray = JSON.stringify(conData);
JSON
[{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362037.111941,"uID":"22489710_3_10"},{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362036.109874,"uID":"22489710_3_10"}]
I've tried the following code but it is returning an empty object.
var obj = {};
for (var i = 0, j = newDataArray.length; i < j; i++) {
if (obj[newDataArray[i].sensorUUID]) {
obj[newDataArray[i]]++;
}
}
console.log(obj);
The full JSON file will have multiple sensor ID's within it, I am looking to return the number of unique sensor ID.
e.g.
22489710 has 10 occurrences
63846683 has 23 occurrences
etc.
the if condition in for loop is correct but you have to initialize count as 1 for the first time you find a particular sensorUUID.
var newDataArray = [{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362037.111941,"uID":"22489710_3_10"},{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362036.109874,"uID":"22489710_3_10"}];
var obj = {};
for (var i = 0, j = newDataArray.length; i < j; i++) {
if (obj[newDataArray[i].sensorUUID]) {
obj[newDataArray[i].sensorUUID]++;
}else{
obj[newDataArray[i].sensorUUID] = 1;
}
}
// obj gives you count for each unique sensorUUID.
console.log(obj);
//if you want total count of all sensorUUID you can sum all the values in obj.
var count = Object.values(obj).reduce((a, b) => a + b, 0);
console.log(count);
you can set a variable count and iterate over the array using Array#forEach and check whether the object has the property sensorUUID using Object#hasOwnProperty if yes, increment the count
var data = [{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362037.111941,"uID":"22489710_3_10"},{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362036.109874,"uID":"22489710_3_10"}];
var count = 0;
data.forEach((x)=>{
if(x.hasOwnProperty('sensorUUID'))
count++;
});
console.log(count);
You can simply iterate through the json array using array.reduce and count the occurances of sensorUUID and store it inside the new object.
var json = [{
"blobJson": "x",
"deviceMfg": 10,
"eventCode": 0,
"sensorClass": 3,
"sensorUUID": "22489710",
"timeStamp": 1500362037.111941,
"uID": "22489710_3_10"
}, {
"blobJson": "x",
"deviceMfg": 10,
"eventCode": 0,
"sensorClass": 3,
"sensorUUID": "22489710",
"timeStamp": 1500362037.111941,
"uID": "22489710_3_10"
}, {
"blobJson": "x",
"deviceMfg": 10,
"eventCode": 0,
"sensorClass": 3,
"sensorUUID": "22489710123",
"timeStamp": 1500362036.109874,
"uID": "22489710_3_10"
}];
let count = json.reduce((newObj, obj) => {
if(newObj[obj.sensorUUID]) {
newObj[obj.sensorUUID] = newObj[obj.sensorUUID]+1;
} else {
newObj[obj.sensorUUID] = 1;
}
return newObj;
}, {});
console.log(count);
https://jsfiddle.net/7jjoches/1/
Using jquery method $.parseJSON you have to convert the JSON string to a JSON object and only then you can work with it.
var conData = '[{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362037.111941,"uID":"22489710_3_10"},{"blobJson":"x","deviceMfg":10,"eventCode":0,"sensorClass":3,"sensorUUID":"22489710","timeStamp":1500362036.109874,"uID":"22489710_3_10"}]';
var newDataArray = $.parseJSON(conData);
console.dir(newDataArray);
var obj = {};
for (var i = 0; i< newDataArray.length; i++) {
obj[newDataArray[i].sensorUUID] = obj[newDataArray[i].sensorUUID] ? obj[newDataArray[i].sensorUUID]+1 : 1;
}
console.log(obj);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Combine values from two arrays in JavaScript

I have an array which looks like:
var data = [{"year":[1981],"weight":[3]},
{"year":[1982],"weight":[4]},
{"year":[1985],"weight":[7]}]
My data series starts with year 1980 and ends with year 1986. My task is to input all missing values into the array; in my case the final array should be:
var data = [{"year":[1980],"weight":[0]},
{"year":[1981],"weight":[3]},
{"year":[1982],"weight":[4]},
{"year":[1983],"weight":[0]},
{"year":[1984],"weight":[0]},
{"year":[1985],"weight":[7]},
{"year":[1986],"weight":[0]}]
I implemented this task in two steps. First I created an empty array with length of seven elements (for years 1980 - 1986) and initialize each element with value {"year": $CURRENT_YEAR, "weight": 0}. Then I loop through data array, find index of current year in the empty array and replace year and weight fields with current values. My code is pasted below.
I wonder if the code could be rewritten in a more elegant way.
// Create empty array
var my_array = []
var length = 7
// 1st step
year = 1980
for (var i = 0; i < length; i++) {
my_array.push({"year": year, "weight": 0});
year++
}
// 2nd step
for (var j = 0; j < data.length; j++) {
curr_year = data[j]["year"][0];
curr_weight = data[j]["weight"][0]
var index = my_array.findIndex(function(item, i) {return item.year === curr_year})
my_array[index] = {"year": curr_year, "weight": curr_weight}
}
It's best to do this job by .map() Besides if you have a large input array it might be wise to set up a hash (lut) in the first place such as;
var data = [{"year":[1981],"weight":[3]},
{"year":[1982],"weight":[4]},
{"year":[1985],"weight":[7]}],
lut = data.reduce((p,c) => p[c.year[0]] ? p : (p[c.year[0]] = c, p), {});
range = [1980,1986],
result = Array(range[1]-range[0] + 1).fill()
.map((_,i) => lut[i+range[0]] ? lut[i+range[0]] : {year: [i+range[0]], weight: [0]});
console.log(result);
You can combine the 2 loops and do both steps in one loop
// Create empty array
var my_array = []
var length = 7
year = 1980
for (var i = 0; i < length; i++) {
// check if there is data for the year
var index = data.findIndex(function(item, i) {return item.year === year});
if(index > -1){ //if there is data, use it
my_array.push({"year": data[index]["year"][0], "weight": data[index]["weight"][0]});
}else{ //put in default data
my_array.push({"year": year, "weight": 0});
}
year++;
}
Find index of element in array each time is bad performance for large data. I can suggest the following algorithm:
// Create empty object and fill it with values where keys are years
var years = {};
data.forEach(item => {
years[item.year[0]] = item.weight[0];
});
// Result array with all years
var result = [];
var startYear = 1980;
var endYear = 1986;
// Generate our result array
for (var i = startYear; i <= endYear; i++) {
// If property for given year (i) exists in "years" object then add it to "result" array
// in other case add default object with weight 0
var o = years[i] ? { year: [i], weight: [years[i]] } : { year: [i], weight: [0] };
result.push(o);
}
You could do this with just find() and while loop.
var data = [{"year":[1981],"weight":[3]},{"year":[1982],"weight":[4]},{"year":[1985],"weight":[7]}];
var i = 1980;
var result = [];
while(i <= 1986) {
var find = data.find(e => e.year[0] == i);
(find) ? result.push(find) : result.push({year: [i], weight: [0]});
i++;
}
console.log(result)
You could also first use map() to get array of years and then use while loop with indexOf().
var data = [{"year":[1981],"weight":[3]},{"year":[1982],"weight":[4]},{"year":[1985],"weight":[7]}];
var i = 1980;
var result = [];
var years = data.map(e => e.year[0]);
while(i <= 1986) {
var ind = years.indexOf(i);
(ind != -1) ? result.push(data[ind]) : result.push({year: [i], weight: [0]});
i++;
}
console.log(result)

Find biggest subarray in a 2d array in JavaScript

Given an array I want to find the largest sub array by the length i.e
var table = [
["Protein",["Grilled Chicken","Lamb"]],
["Fats",["rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"]],
["Vegatables",["Carrots","Eggs","Milks","Peppers"]]
];
I want it to return ["Carrots","Eggs","Milks","Peppers"]
Heres my code
function findBiggestSubArray(array){
var biggestArrayIndex = 0;
for(var i=0;i<array.length;i++){
if(i === (array.length-1)){
//We have reached the end of the array then return the array
console.log("Reached the End");
return array[biggestArrayIndex];
} else {
if(!array[biggestArrayIndex][1].length >= array[i][1].length){
biggestArrayIndex = i;
}//End of Inner else block
}//End of Outer else block
}//End of forloop
}
General solution, to find the most largest array in an array-structure:
I would do it with recursion, so the most biggest Array will be found, in any depth..
/**
* array -> The array to check,
* biggestArray -> The most biggestArray found so far
*/
function findBiggestArray(array, biggestArray){
biggestArray = biggestArray || [];
if (array.length > biggestArray.length)
biggestArray = array;
for (var i = 0; i < array.length; i++) {
if (array[i] instanceof Array)
biggestArray = findBiggestArray(array[i],biggestArray)
}
return biggestArray;
}
var multiArray = [
["1", "2", ["234", "334"]],
[1,2,3,4,5, [1,2,3,4,5,6,7,7]]
]
var biggest = findBiggestArray(multiArray)
console.log(biggest)
// This also works!
console.log(findBiggestArray([1, [1,2,3]]))
Oneliner for this special case
// Sort the array by the length of the subarray at position 1, and return the first item
var category = table.sort(function(a, b) { return b[1].length - a[1].length })[0]
// ES6-Syntax
var category = table.sort((a, b) => b[1].length - a[1].length)[0]
category // => ["CategoryName", [ITEMS..]]
I would do this way (see the comments in the code for explanation):
var table = [
["Protein", ["Grilled Chicken", "Lamb"]],
["Fats", ["rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"]],
["Vegatables", ["Carrots", "Eggs", "Milks", "Peppers"]]
];
function findBiggestSubArray (array) {
// Initialise empty array.
var bigSubArray = ["", []];
// Loop through the given array.
for (var i = 0; i < array.length; i++) {
// Check if the current biggest one is bigger than the saved array.
if (array[i][1].length > bigSubArray[1].length) {
// If bigger, replace it with current array.
bigSubArray = array[i];
}
}
// Return the biggest sub array.
return bigSubArray[1];
}
console.log(findBiggestSubArray(table));

Categories