For each entry in a sub array add values - javascript

let b = [];
this.state.sidejobs.forEach((user) => {
console.log(user);
if (!b.hasOwnProperty(user.jobworker)) b[user.jobworker] = 0;
b[user.jobworker] += user.duration;
});
One entry in jobworker has an array with two ids... how do i split it and add the duration respectively.
Name ID Total Hours
Mike Smith 281 5
284,281 5
John Doe 284 21
Chris Smith 283 23

let b = [];
this.state.sidejobs.forEach((user) => {
var jobworkers = user.jobworker.toString().split(",");
for (var i = 0; i < jobworkers.length; i++) {
var worker = jobworkers[i].trim();
if (!b.hasOwnProperty(worker)) b[worker] = 0;
b[worker] += user.duration;
}
});

First of all, is b an array or an object? Or are you using it as both? I suspect you meant for it to be an anonymous object.
let b = {};
Secondly, it would really help to know the exact structure of user.jobworker (eg: call "JSON.stringify(user.jobworker)"). For now, I will assume that the structure of the user object is as follows:
{
name: "Mike Smith",
id: 281,
duration: 5,
jobworker: [284, 281]
}
If that is the case, all you have to do is
let b = {};
this.state.sidejobs.forEach((user) => {
for (var i = 0; i < user.jobworker.length; i++) {
if (!b.hasOwnProperty(user.jobworker[i])) b[user.jobworker[i]] = 0;
b[user.jobworker[i]] += user.duration;
}
});
If instead user.jobworker contains a comma-delimited string of ids (eg: user.jobworker = "284,281") then you will have to split the string first:
this.state.sidejobs.forEach((user) => {
var jobworkers = user.jobworker.split(",");
for (var i = 0; i < jobworkers.length; i++) {
var worker = jobworkers[i].trim();
if (!b.hasOwnProperty(worker)) b[worker] = 0;
b[worker] += user.duration;
}
});

Related

Reading data from Firebase to Javascript

I am trying to list all data from Javascript keys Object when I put it in console log there is all information, but when I want to use InnerHTML I keep getting the first object only shown.
function gotData(data){
var scores = data.val();
var keys = Object.keys(scores);
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
var pro = scores[k].result;
var doc = document.getElementById("result").innerHTML = pro;
}
}
In this case, it will give me only a result of first element from my Firebase
Thanks
Please check out this stackblitz-demo, looks like your missing one small thing if I am understanding what your expected outcome is.
onClick() {
const scores = [{
'one': 1
}, {
'two': 2
}, {
'three': 3
}, {
'four': 4
}, {
'five': 5
}];
var keys = Object.keys(scores);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
const pro = scores[k].result;
// here the += is what i think you're missing.
const doc = document.getElementById("example").innerHTML += k;
}
}
The issue is that you are overriding innerHTML each time. Instead, you need to append to the existing innerHTML. Change the last line to...
const doc = document.getElementById("example").appendChild(document.createTextNode(k))
appendChild is also much faster than setting innerHTML
.hasOwnProperty is how to see just your stored values. Does this help?
d = snap.val();
for (var k in d) {
if (d.hasOwnProperty(k)) {
if (isObject(d[k]){
console.log(k, d[k]);
} else {
console.log (k);
}
}
}
function isObject(obj) {
return obj === Object(obj);
}

JavaScript module pattern gives unexpected results

I am just messing around with generating random human names in JS. I wanted to also practice using the module pattern but I can't get my function to return a normal array.
What I want to save is how often a letter (or set of letters) shows up after another letter.
So with 'jacob' and 'jarod' I should see that the letter 'a' came after the letter 'j' 2 times like this: myArray[j][a] //2
BUT what I have instead somehow turned the array into a set of properties and to figure out that 'a' comes up 2 times I have to check it this way : myArray.j.a //2
can someone explain why this is and how I can fix it?
var names = ['jacob', 'cameron', 'zach', 'lake', 'zander', 'casey', 'carl', 'jeff', 'jack', 'jarod', 'max', 'cat', 'mallory', 'dana', 'hannah', 'stu', 'abrham', 'isaac'];
var probabilities = (function(){
var nextLetterProbability = [];
function addProbability(index, letters){
if(nextLetterProbability[index] !== undefined){
if(nextLetterProbability[index][letters] !== undefined){
nextLetterProbability[index][letters] = nextLetterProbability[index][letters] + 1;
}
else
nextLetterProbability[index][letters] = 1;
}
else{
nextLetterProbability[index] = [];
nextLetterProbability[index][letters] = 1;
}
}
return {
learn:function(names, chainLength){
for (var i = 0; i < names.length; i++) {
var name = names[i];
for (var j = 0; j < name.length - chainLength; j++) {
var start = name[j];
var next = name.slice(j + 1, j + chainLength + 1)
addProbability(start, next);
};
};
},
getLearnedArray:function(){
return nextLetterProbability;
}
}
})();
var nextLetterProbability = []; needed to be var nextLetterProbability = {}; because it is an associative array and is handled as an object.

Count distinct elements in array

I have data that comes from my server to datatables.
I'm successfully populating my table but in footer callback I want to do some statistics.
Lets say I have data like so:
var data = [{
date: '2013-05-12',
holiday: "One type of holiday",
dayType: "Weekend"
}, {
date: '2013-05-13',
holiday: "Another type",
dayType: "Weekend"
}, {
date: '2013-05-14',
holiday: "Another type",
dayType: "Work"
}, {
date: '2013-05-15',
holiday: "",
dayType: "Work"
}];
I would like to count number of days with different holidays.
Here is result I would like to get:
var summary= [
{
"One type of holiday": {
"work": 0,
"weekend": 1
}
},
{
"Another type": {
"work": 1,
"weekend": 1
}
}];
I've created a very simple code to simply aggregate holidays:
for (var i = 0; i < data.length; i++) {
//console.log(data[i].holiday);
/*other stuff here*/
if (data[i].holiday.length > 0)
summary[data[i].holiday] = summary[data[i].holiday] + 1 || 1;
}
but this gives me invalid results, because in my data array holiday contains spaces.
I need a way to fix this and to split holidays based on dayType.
MY SOLUTION:
My version of answer:
var summary = {}, d, tmp, type;
for (var i = 0; i < data.length; i++) {
var d = data[i];
if (d.holiday.length > 0) {
type = d.dayType == 'Weekend' || d.dayType == 'Free' ? 'Weekend' : 'Work';
tmp = summary[d.holiday];
if (!tmp) {
tmp = {
Weekend: 0,
Work: 0
};
summary[d.holiday] = tmp;
}
summary[d.holiday][type] += 1;
}
}
Because this is modified version of #Arun answer I'm not posting this as standalone answer.
I find my version easier to understand, hope someone find's it useful.
Try
var summary = [], summaryMap = {}, d, map, m;
for (var i = 0; i < data.length; i++) {
var d = data[i];
map = summaryMap[d.holiday];
if(!map){
map = {
Work: 0,
Weekend: 0
};
m = {};
m[d.holiday] = map;
summary.push(m);
summaryMap[d.holiday] = map;
}
map[d.dayType] += 1;
}
console.log(summary);
console.log(JSON.stringify(summary));
Demo: Fiddle
go for
console.log(Object.keys(summary).length);
instead of
console.log(summary.length);
Because you can get the number of elements in a js object by using the length attribute.
note: using Object.keys may lead you to browser compatibility issues. As its supported form IE 9 and Firefox 4. See more info in this MDN article.
you can find more info and solutions for this problem in this answer.
see the updated fiddle.
Here's my attempt:
var summary = [];
var holidayTypes = [];
var dayTypes = [];
//first work out the different types of holidays
for (var i = 0; i < data.length; i++) {
if(holidayTypes.indexOf(data[i].holiday) == -1){
//this is a new type of holiday
holidayTypes.push(data[i].holiday);
}
if(dayTypes.indexOf(data[i].dayType) == -1){
//new type of day.
dayTypes.push(data[i].dayType);
}
}
console.log('types of holiday: ' + JSON.stringify(holidayTypes));
console.log('types of day: ' + JSON.stringify(dayTypes));
for(index in holidayTypes){
var typeobj = {};
//create an object for each type of holiday
typeobj[holidayTypes[index]] = {};
for(index2 in dayTypes){
//initialize a count for each type of day
typeobj[holidayTypes[index]][dayTypes[index2]] = 0;
//iterate through the data and count the occurrences where the day AND holiday match.
//if they do, iterate the value.
for (var j = 0; j < data.length; j++){
if((data[j].holiday == holidayTypes[index])
&& (data[j].dayType == dayTypes[index2])){
typeobj[holidayTypes[index]][dayTypes[index2]]++;
}
}
}
summary.push(typeobj);
}
console.log(JSON.stringify(summary));
Fiddle here
Output:
[{"One type of holiday":{"Weekend":1,"Work":0}},{"Another type":{"Weekend":1,"Work":1}},{"":{"Weekend":0,"Work":1}}]
It works but is unlikely to be as efficient as the guys above!

need to implement my algorithm using javascript

I have made small algorithm and want to implement it using javascript. Here is my algorithm
I have a data in data.json file in this format
[
"109 200",
"109 201",
"102 202",
"103 202"
]
What I am trying to do is
Create four array containers i.e. c1, c2, c3 and c4.
Put above data in c1 container as it is
loop through c1 and put the data in c4 in following format
"109",
"200",
"109",
"201",
"102",
"202",
"103",
"202"
loop through c1 and put them in c2 in this format
"109,200"
then check if c3 is empty then read first value from c2 and push it in c3.
repeat step 4 but this time put second data i.e. "109 201" from c1 in c2 in this format
"109,201"
then check if c3 is not empty then loop through c2 and check if any of these two values are repeated in c4. If it is repeated then repeat step 6 and 7 until it finds least amount of numbers from data.json.
This algorithm is not efficient but still I want to use this.
Here is my code.
var teams = [],
c1 = [], arr = [], left = [], right = [], j = 0,
show = function () {
var span = $('#list');
$.getJSON('data/data.json', function (ids) {
//c1.push(c);
for (var i = 0; i < ids.length; i++) {
var a = smallcontainer(ids);
var b = bigcontainer(ids);
var c;
if (c1 == "") {
c = a[0].split(" ");
console.log(c);
} else {
}
//console.log(c);
var id = ids[i];
teams = id;
$('<li>' + id + '</li>').appendTo(span);
}
});
},
smallcontainer = function (teams) { //arr
arr = [teams[j]];
j++;
return arr;
},
bigcontainer = function (ids) { //c3. in code it is left+right=result
for (var i = 0; i < ids.length; i++) {
var splitted = ids[i].split(" ");
left.push(splitted[0]);
right.push(splitted[1]);
}
var result = left.concat(right);
};
Update
data inside data.json file has four teams with two members in each team in this form
"109 200" = Team 1
"109 201" = Team 2
"102 202" = Team 3
"103 202" = Team 4
So now I have to compute the smallest number of people and it has to select one member from each team from this list and show their IDs. So the output for above would be
109
202
Latest update
I am still waiting for help
Solution
Here is the solution with the help of AlexBEll and PAEz. I used solution below which was basically solved by AlexBell
var data = [
"1009 2000",
"1009 2001",
"1002 2002",
"1003 2002",
"1004 2003",
"1005 2004",
"1006 2005",
"1007 2006",
"1007 2007",
"1008 2008",
"1009 2008",
"1010 2009",
"1011 2010",
"1012 2010"
];
var first = [], second = [], result = {}, out = '';
//Separe the ids
for(var i = 0; i < data.length; i++){
var el = data[i].split(' ');
first[i] = el[0];
second[i] = el[1];
}
for(var k = 0; k < first.length; k++){
//Count the elements
var nOfFirst = countElemnts(first, first[k]);
var nOfSecond = countElemnts(second, second[k]);
//If the first is in more that second take it
if(nOfFirst > nOfSecond){
result[first[k]] = 0;
//Else take the second
}else if(nOfFirst < nOfSecond){
result[second[k]] = 0;
//If is only one take it
}else{
result[first[k]] = 0;
}
}
function countElemnts(arr, el){
var count = 0;
for(var j = 0; j < arr.length; j++){
if(arr[j] == el)
count++;
}
//console.log(el+' : '+count);
return count;
}
for(var n in result){
out += 'The id n: '+n+' is in the list\n';
}
alert(out);
Does this work?....
var teams=[
"109 200",
"109 201",
"102 202",
"103 202"
];
var members ={};
var matesId='109';
// Members that won
var wins={};
// First lets find out how many teams a member is in
for (var i=0,length=teams.length; i<length;i++){
var temp = teams[i].split(' ');
for (var z=0,zlength=temp.length;z<zlength;z++){
if (!members[temp[z]]) members[temp[z]]={wins:0,totalTeams:0,id:temp[z]};
members[temp[z]].totalTeams=members[temp[z]].totalTeams+1;
}
teams[i]=[members[temp[0]],members[temp[1]]];
}
for (var i=0,length=teams.length; i<length;i++){
var member1=teams[i][0];
var member2=teams[i][1];
if (member1.totalTeams>member2.totalTeams){
member1.wins=member1.wins+1;
} else if (member1.totalTeams<member2.totalTeams){
member2.wins=member2.wins+1;
} else {
member1.wins=member1.wins+1;
member2.wins=member2.wins+1;
}
}
for (var i=0,length=teams.length; i<length;i++){
var member1=teams[i][0];
var member2=teams[i][1];
if (member1.wins>member2.wins){
if (wins[member2.id]!==true) wins[member1.id]=true;
} else if (member1.wins<member2.wins){
if (wins[member1.id]!==true) wins[member2.id]=true;
} else if (!wins[member1.id] && !wins[member2.id]) {
if (member1.id==matesId && member2.id==matesId) {
wins[matesId]=true;
} else{
// A draw, so pick one
Math.round(Math.random())==1 ? wins[member2.id]=true : wins[member1.id]=true;
}
}
}
var keys=Object.keys(wins);
var results=[];
results.push(keys.length);
for (var i=0,length=keys.length; i<length;i++){
results.push(keys[i]);
}
results=results.join('\n');
document.querySelector('#output').innerText=results;​
http://jsfiddle.net/PAEz/dLUqj/3/
EDIT: Updated it so its a little easier to read.
EDIT: Realised you dont need a draw and win, just a win will do.
LAST EDIT: Noticed one small error, it should all be right now.

Javascript alphabetical grouping

I have a json array of objects that look like this: {id:'the id', name:'the name'}; and I need to loop over the array and group each object alphabetically by it's name attribute. Is there a way to do this without using a switch / if statement with every letter in it?
What I don't want to do is something like this:
if(data[i].name..slice(0, 1) == 'a') {
...
}
It's a large array, with almost a 1,000 objects in it. My goal is eventually append them to a dive so it looks something like this:
4
4 pints
4 biscuits
A
Apple
Alex
Adam
B
Bob
Billy
you can loop throught your collections like this:
var groupedCollection = {};
for(...){//loop throug collection
var firstLetter = data[i].charAt(0);
if(groupedCollection[firstLetter] == undefined){
groupedCollection[firstLetter] = [];
}
groupedCollection[firstLetter].push(data[i]);
}
//groupedCollection now contait data in the form of {a: [], b:[], etc...}
Bubble sort will do this job for you. Example:
// sample array
var myArr = [
{id:"00", name:"Billy"},
{id:"00", name:"Apple"},
{id:"00", name:"4 biscuits"},
{id:"00", name:"Adam"},
{id:"00", name:"Alex"},
{id:"00", name:"4 pints"},
{id:"00", name:"Bob"}
];
// standard bubble sort algorithm
function bubbleSortByName(arr) {
for (var x = 0; x < arr.length; x++) {
for(var y = 0; y < arr.length-1; y++) {
// compare arr[].name.toLowerCase() i.e. b > a
if(arr[y].name.toLowerCase() > arr[y+1].name.toLowerCase()) {
var tmp = arr[y+1];
arr[y+1] = arr[y];
arr[y] = tmp;
}
}
}
return arr;
}
// sort the array
var sortedArr = bubbleSortByName(myArr);
// print the results
for (var i=0; i<sortedArr.length; i++)
document.write(sortedArr[i].name+"<br/>");
Or the same idea with an insertion sort algorithm:
// standard insertion sort algorithm
function insertionSortByName(arr) {
for(var j = 1; j < arr.length; j++) {
var key = arr[j];
var i = j - 1;
while(i >= 0 && arr[i].name.toLowerCase() > key.name.toLowerCase()) {
arr[i+1] = arr[i];
i = i - 1;
}
arr[i+1] = key;
}
return arr;
}
ES7 syntax
const sortAndGroup = async () => {
const sortedData = data.sort();
const reducedData = sortedData.reduce((items, dataElement) => {
if (!items.find(item => item.header === dataElement.charAt(0))) {
items.push({ header: dataElement.charAt(0) });
}
items.push({ name: dataElement });
return items;
}, []);
return reducedData.map(item => item.header || item.name);
};
sortAndGroup().then(result => console.log(result));

Categories

Resources