Increment value of List Object array in Object array [duplicate] - javascript

This question already has answers here:
Javascript array with for loop, returns only last element
(3 answers)
Closed last month.
I create an object name month, List year and object list. Then I add list year to object list as keys and add object month to list of object list.
var year = [2021, 2020];
var month = {"jan": 0, "feb": 0, "mar": 0};
var list={};
for (let i = 0; i < 2; i++) {
list[year[i]] = [month];
}
list['2021'][0]['feb']+=1;
console.log(list);
Result: list={'2021': [{'jan':0, 'feb':0, 'Mar':0}], '2020': [{'jan':0, 'feb':0, 'Mar':0}]}
Results as I wanted, but problem occurred when I try to increment the value of each month by year.
Example: list['2021'][0]['feb']+=1;
What I want: list={'2021': [{'jan':0, 'feb':1, 'Mar':0}], '2020': [{'jan':0, 'feb':0, 'Mar':0}]}
What I get: list={'2021': [{'jan':0, 'feb':1, 'Mar':0}], '2020': [{'jan':0, 'feb':1, 'Mar':0}]}

Try This
var year = [2021, 2020];
var month = {"jan": 0, "feb": 0, "mar": 0};
var list={};
for (let i = 0; i < 2; i++) {
list[year[i]] = [Object.assign({}, month)];
}
list['2021'][0]['feb']+=1;
console.log(list);

Related

Why is my input parameter being modified in this code snippet? [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 3 years ago.
Why is my input parameter inArr being modified when I update local variable arr in the JavaScript code below?
function test(inArr) {
var arr = inArr;
for (let i = 0; i < 3; i++) {
arr.push(i);
console.log( "arr = ", arr, "inArr = ", inArr );
}
}
test([]);
This outputs:
arr = [ 0 ] inArr = [ 0 ]
arr = [ 0, 1 ] inArr = [ 0, 1 ]
arr = [ 0, 1, 2 ] inArr = [ 0, 1, 2 ]
JavaScript arrays are assigned by reference, so when you make your assignment, both variables are pointing to the same array in memory. Any change to one will also change the other.
You can create a new array with those values using the spread operator:
var arr = [...inArray];
because they are the same.
function test(inArr) {
var arr = [].concat(inArr);
for (let i = 0; i < 3; i++) {
arr.push(i);
console.log( "arr = ", arr, "inArr = ", inArr );
}
}
test([]);

JSON data - Group by days of the week(Sun,Mon,Tue, Wed,Thu,Fri,Sat) using Javascript/Jquery

The below function returns chart data
The output returned by the above function is in the below format
[Object { date=Date, value=112, volume=1469}, Object { date=Date, value=124, volume=539}, Object { date=Date, value=114, volume=859}, Object { date=Date, value=123, volume=1284}, Object { date=Date, value=113, volume=1382}, Object { date=Date, value=129, volume=1353}]
From the output generated by getChartData above, I'm eager to see an output of the below kind where01,02 etc are the month numbers. This is basically aggregating data to the day of week level per month.
[{'dayofweek':'01-SUN','value':xxx,'volume':'yyy},{'dayofweek':'01-MON','value':xxx,'volume':'yyy},{'dayofweek':'01-TUE','value':xxx,'volume':'yyy},{'dayofweek':'01-WED','value':xxx,'volume':'yyy},{'dayofweek':'01-THU','value':xxx,'volume':'yyy},{'dayofweek':'01-FRI','value':xxx,'volume':'yyy},{'dayofweek':'01-SAT','value':xxx,'volume':'yyy}]
I were to JSON.stringify the output of getChartData the array, the output looks as below ( Showing this so that the value of 'date' field is visible
[{"date":"2014-10-06T06:00:00.000Z","value":119,"volume":1417},{"date":"2014-10-07T06:00:00.000Z","value":126,"volume":1421},{"date":"2014-10-08T06:00:00.000Z","value":140,"volume":850}]
The above array has several hundred objects. I'm trying to aggregate this to achieve the sum of value & volume fields month by month at a day of the week level ( Total for Sunday, Monday etc .... Sat).
The object array can have any field. I mean, I'd like to write a dynamic function where the first element of every object will be a date field denoted by any variable name (date, xdate,ydate whatever). The rest of the fields apart from the first field(In sometimes there may be 2 fields, 3 fields or 'n' number of fields) needs to be added up & aggregated to day of week level per month
Here is what I'm doing
function setGroupingDayOfWeek(thisObj) {
var chartData = getChartData("chartdiv");
var keysOnly = Object.keys(chartData[0]);
var objStruct = getObjStruct(keysOnly);
var chartFeedJson = updatejsonStruct(objStruct,chartData)
}
function getObjStruct(keyArray) {
// var arrToObjContent = _.values(Object.keys(jsonData[0])),
var arrToObjContent = keyArray,
dayOfWeek = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"],
i = 0,
z,
arrToObjLength = arrToObjContent.length,
dayOfWeekLength = dayOfWeek.length,
jsonObj = {},
newObj,
key,
value;
for (; i < dayOfWeekLength; i++) {
newObj = {};
for (z = 0; z < arrToObjLength; z++) {
key = arrToObjContent[z];
if (key === arrToObjContent[0]) {
value = dayOfWeek[i];
} else {
value = "";
}
newObj[key] = value;
}
jsonObj[i] = newObj;
}
return jsonObj;
}
function updatejsonStruct(objStruct,chartData) {
var baseStruct = objStruct,
chartDataFormatted = JSON.stringify(chartData);
// The idea here is to first group it by months & then loop through & sum up all Sundays, Mondays etc to the end of week
var groupedByMonth = _.groupBy(chartDataFormatted , function (item) {
return item[0].substring(0, 9);
});
console.log(groupedByMonth);
}
This isn't grouping data by months. obviously, I'm doing the wrong thing in the aggregation. A few questions with regards to this -
1) how could I use chartData which is the non-strigified version & group it by months
2) if (1) is hard/complex, how could I use chartDataFormatted to do the grouping by months
3) At the end of this, I'd like to update the objStruct with the details of the calculation ( Grouping by days ogf the week)
Now, this is entirely what I thought of doing as I don't have good experience with Jquery or other cool javacript libraries. If there is a better of doing this (Say without the need of baseStruct or directly aggregating data into the needed format), I'm excited to get some guidance.
If I've missed explaining something you think is needed or if I've not communicated clearly, please let me know. I'll try my best to clarify. I've been stuck with this with no much ideas. Hence, requesting help please.
Trying to reduce grouping to Just Mon through to Sat -
Obviously I'm not accessing the object array in the right way. The idea is to create a master array having Mon - Sun as one of the many fields in an object array containing 7 objects ( One object for each day of the week). The final object array should have just 7 objects one per day of the week.
How exactly can I look up the obejct array & check the value of zeroth field within it?
var days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]
var chartData = getChartData("chartdiv");
//use var chartData = getChartData("chartdiv") here instead;
keys = Object.keys(chartData[0]);
var newObjStruct = [{},{},{},{},{},{},{}];
for(var k = 0; k < days.length; k++){
for(var i = 0; i < keys.length; i++){
if (i === 0) {
newObjStruct[k]['dayOfWeek' ] = days[k];
} else {
newObjStruct[k][keys[i]] = "";
}
}
}
console.log(newObjStruct);
for (j=0; j<chartData.length; j++){
var castObj = JSON.stringify(chartData[j]);
console.log(castObj[0]);
//val.date.getDay();
for(k = 0; k < newObjStruct.length; k++) {
if (newObjStruct[k][0] === days[day]) {
for(var i = 0; i < keys.length; i++){
newObjStruct[k][i] += chartData[keys[i]];
}
}
}
}
See the following JS Fiddle link: https://jsfiddle.net/ahu6kLvr/1/
var days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];
var testArray = [{"date":"2014-10-06T06:00:00.000Z","value":119,"volume":1417},{"date":"2014-10-06T06:00:00.000Z","value":119,"volume":1417},{"date":"2014-10-07T06:00:00.000Z","value":126,"volume":1421},{"date":"2014-10-08T06:00:00.000Z","value":140,"volume":850}];
var groupResult = _.groupBy(testArray, function (value) {
var d = new Date(value.date);
return (d.getMonth()+1) + "-" + days[d.getDay()]
});
var result = [];
_.each(groupResult, function (value, key) {
var volumeSum = 0;
var valueSum = _.reduce(value, function(memo, obj){
//valueSum += obj.value;
volumeSum += obj.volume;
return memo + obj.value;
}, 0);
result.push({ dayofweek: key, value: valueSum, volume: volumeSum });
})
console.log(result);
You can first group by month and day, then do a reduce to sum all the values and volume. Regarding your comment to other answer, I think it is very difficult to make the fields dynamic.
EDIT:
Check the updated fiddle: https://jsfiddle.net/ahu6kLvr/1/
var result = [];
_.each(groupResult, function (value, key) {
var doc = _.reduce(value, function(memo, obj){
delete obj.date;
if (typeof(memo) == "number") {
return obj;
} else {
for (var key in memo) {
memo[key] += obj[key] || 0;
}
return memo;
}
}, 0);
doc.dayOfWeek = key;
result.push(doc);
})
This is partially dynamic. The condition applies that the first key of the object is a date object.
var days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]
//I have used new Date which gets the current date, you don't need that.
var chartData = [{ date:new Date, value:112, volume:1469}, { date:new Date, value:124, volume:539}, { date:new Date, value:114, volume:859}, { date:new Date, value:123, volume:1284}, { date:new Date, value:113, volume:1382}, { date:new Date, value:129, volume:1353}];
//use var chartData = getChartData("chartdiv") here instead;
keys = Object.keys(chartData[0]);
var newA = chartData.map(function(val, i){
day = val.date.getDay();
month = (val.date.getMonth() + 1).toString();
month = month.length == 2 ? month : '0' + month;
rtn = {};
for(var i = 0; i < keys.length; i++){
if(i == 0){
rtn[ 'dayOfWeek' ] = month + '-' + days[day];
} else {
rtn[ keys[i] ] = val[keys[i]];
}
}
return rtn;
})
document.write(JSON.stringify(newA))

Create X amount of empty arrays based on input [duplicate]

This question already has answers here:
Declare variables programmatically?
(3 answers)
Closed 7 years ago.
A user dynamically chooses a value X. Based on the value, X, I want to create unique empty arrays. How would I go about that?
For example, user chooses 4.
I want the following output:
var array1 = [];
var array2 = [];
var array3 = [];
var array4 = [];
Is there a way to properly doing this?
You can specify the name of a property on an object using the square brackets with a string input:
var obj = {};
var numberOfArrays = 4;
for(var i = 1; i <= numberOfArrays; i++){
obj['array' + i] = []; // Specify the name of the array property
}
console.log(obj); // Logs an object which has 4 empty arrays
Just to complement Steven`s answer, you could also create an array of arrays:
var numberOfArrays = X;
var arr = [];
for(var i = 0; i < numberOfArrays; i++){
arr.push(new Array());
}

Create an array of sub-arrays with the value of an element and the number of times it has repeated in JavaScript

I'm trying to take an array (for an example, an array of years) and then make a new array of sub-arrays which tells, firstly, the unique element in the original array and, secondly, how many time it was repeated.
For example, lets say I start of with an array of numbers [1999, 1999, 2000, 2005, 2005, 2005, 2015]
I would like my function to return an array like [[1999, 2], [2000, 1], [2005, 3], [2015, 1] ]
because the year 1999 was repeated twice, the year 2000 was was not repeated, the year 2005 was repeated three times, etc.
I can successfully make a new array that removes the duplicates, but Im getting some weird behavior when it comes to making my sub-arrays.
EDIT
Here was my own faulty solution, in case anyone wants to point out what i did wrong.
var populateYearsList = function(yearsDuplicate){
var uniqueYears = [];
for (var i=0; i < yearsDuplicate.length; i++){
if(uniqueYears.indexOf(yearsDuplicate[i]) == -1){
uniqueYears.push(yearsDuplicate[i])
} else {
console.log("duplicate found") };
}
console.log (uniqueYears)
};
I ran into the problem of trying to change uniqueYears.push(yearsDuplicate[i]) into uniqueYears.push([ yearsDuplicate[i], 1 ]) and then trying to replace my console.log into some sort of incremented counter.
It is as easy as:
var input = [1999, 1999, 2000, 2005, 2005, 2005, 2015];
var uniq = [];
input.forEach(function(n){
if (uniq.indexOf(n)<0)
uniq.push(n);
});
var output = uniq.map(function(n){
return [n, input.filter(function(m){ return m == n }).length]
});
Quick explanation how it works
Given the input array, map its unique version to the new array with this mapping:
element ---> [ element, the number of occurrences in the original array ]
EDIT NOTE:: FIXED the previous solution which might introduced duplicate element.
This is how I would do it:
var input = [1999, 1999, 2000, 2005, 2005, 2005, 2015];
function numberOfOccurancesArray (input) {
var result = {};
for (var i = 0; i < input.length; i++) {
var currentYear = input[i];
// if there is an element with the name of the currentYear
if (result[currentYear]) {
// increace its prop `count` with 1
result[currentYear].count += 1;
} else {
// if not present, create it
result[currentYear] = {
year: currentYear,
count: 1
}
}
}
return result;
}
Here is sample code : JsFiddle
If you want to play with functional paradigms, reduce it to a dictionary and then map the keys to a tuple.
var yearToCounts = input.reduce(function(counts, year) {
if (year in counts) {
counts[year]++;
} else {
counts[year] = 1;
}
return counts;
}, {});
return Object.keys(yearToCounts).map(function(year) {
return [year, yearToCounts[year]];
});
var years = [1999, 1999, 2000, 2005, 2005, 2005, 2015];
var occurences = [];
for(var i = 0; i < years.length; i++ ) {
var year = years[i];
if(typeof occurences[year] === 'undefined') {
occurences[year] = 1;
} else {
occurences[year]++;
}
}
occurences = occurences.map(function(occurences, year) {
return [year, occurences];
});
console.log(occurences);
EDIT: Much faster solution
var results = [];
var uniq = [];
var counts = [];
var i = 0;
for (i; i < years.length; i++) {
var year = years[i];
var indexOf = uniq.indexOf(year);
if (indexOf < 0) {
uniq.push(year);
counts[uniq.length - 1] = 1;
} else {
counts[indexOf] += 1;
}
}
i = 0;
for (i; i < uniq.length; i++) {
results.push([uniq[i], counts[i]]);
}
return results;

Count occurrences of array elements with JavaScript [duplicate]

This question already has answers here:
How to count duplicate value in an array in javascript
(35 answers)
Closed 7 years ago.
I have this JavaScript array with length 129.
var fullnames = [Karri, Ismo, Grigori, Ahmed, Roope, Arto .....]
I would like to find how many times those names appeared in an array and store that information in an array like this:
var counter = [2, 5, 7, ..]
where Karri occured in fullnames array 2 times, Ismo occured 5 times etc. Any ideas about how to do it?
This is the best - and simple - way I can think of:
var fullnames = ["Karri", "Ismo", "Grigori", "Ahmed", "Roope", "Ahmed", "Karri", "Arto", "Ahmed"];
var counts = {};
for (var i = 0; i < fullnames.length; i++)
{
if (!counts.hasOwnProperty(fullnames[i]))
{
counts[fullnames[i]] = 1;
}
else
{
counts[fullnames[i]]++;
}
}
console.log(counts);
Original Fiddle.
Using an array to store the counts doesn't makes much sense, so I used an object instead.
I am assuming that fullnames is array of strings. If so, you can do it like so:
var occurences = { };
for (var i = 0; i < fullnames.length; i++) {
if (typeof occurences[fullnames[i]] == "undefined") {
occurences[fullnames[i]] = 1;
} else {
occurences[fullnames[i]]++;
}
}
console.log(occurences); // Prints out something like: {"Karri": 2, "Ismo": 5, ...}
var fullnames = ['Karri', 'Ismo', 'Grigori', 'Karri', 'Ismo', 'Grigori', 'Grigori', 'Karri', 'Ismo', 'Grigori', 'Grigori'];
var counts = [];
fullnames.forEach(function(_item) {
if(typeof counts[_item] === 'undefined') counts[_item] = 1;
else counts[_item]++;
});
var result = [];
for(i in counts) result.push(counts[i]);
console.log(result);
// outputs [3, 3, 5]

Categories

Resources