I am working on application which I need to do grouping of different sets of javascript object and those will be based on month,day and year.
For day I am doing like below
var calculateByDay = function(inputList){
var outPutList = [];
var result = {}
var item = null, key = null;
for(i=0; c<inputList.length; i++) {
item=inputList[c];
key = Object.keys(item)[0];
item=item[key];
if(!result[key]) {
result[key] = item;
}
else {
result[key] += item;
}
for (r in result)
{
var docs = {};
docs["date"] = r;
docs["amount"] = result[r];
outPutList.push(docs);
}
}
return outPutList;
}
How can I improve above code and use it for month and year calculation also?
I went thorough underscore.js and it has a groupBy method. but seems not fits with my requirement.
I want to group by months and year also,
for
var inputList = [{"2012-12-02T00:00": 2000}, {"2013-01-01T00:00": 1200},{"2013-02-02T00:00": 550}, {"2013-02-02T00:00": 1000}];
The output should be:
Monthly :
[{"December 2012": 2000}, {"January 2013": 1200},{"February 2013": 1550}];
Yearly
[{"year 2012": 2000}, {"year 2013": 2750}];
And it seems I need to this kind of map,reduce approach for large data(array sets), is there any other library or practices I can do to make the code solid?
Thanks in advance.
Given a slightly different structure of data:
var data = [{
"date": "2011-12-02T00:00",
"value": 1000
}, {
"date": "2013-03-02T00:00",
"value": 1000
}, {
"date": "2013-03-02T00:00",
"value": 500
}, {
"date": "2012-12-02T00:00",
"value": 200
}, {
"date": "2013-04-02T00:00",
"value": 200
}, {
"date": "2013-04-02T00:00",
"value": 500
}, {
"date": "2013-03-02T00:00",
"value": 500
}, {
"date": "2013-04-12T00:00",
"value": 1000
}, {
"date": "2012-11-02T00:00",
"value": 600
}];
You could use underscore:
var grouped = _.groupBy(data, function(item) {
return item.date;
});
var groupedByYear = _.groupBy(data, function(item) {
return item.date.substring(0,4);
});
var groupedByMonth = _.groupBy(data, function(item) {
return item.date.substring(0,7);
});
console.log(groupedByYear);
See related answer: Javascript - underscorejs map reduce groupby based on date
Please see if the following refactor is useful for you
http://jsfiddle.net/wkUJC/
var dates = [{"2012-12-02T00:00": 2000}, {"2013-01-01T00:00": 1200},{"2013-02-02T00:00": 550}, {"2013-02-02T00:00": 1000}];
function calc(dates) {
var response = {};
dates.forEach(function(d){
for (var k in d) {
var _ = k.split("-");
var year = _[0]
var month = _[1]
if (!response[year]) response[year] = {total: 0}
response[year][month] = response[year][month] ? response[year][month]+d[k] : d[k]
response[year].total+= d[k]
}
});
console.log(response);
return response;
}
calc(dates);
Related
I have an array this the format below. Trying to push multiple entire subarrays (starting with A-) fulfilling a condition to a new array and keep the array format. Have no success with the code below.
Array:
{"#VER": {
"A-1": {
"verdatum": "2016-07-08",
"vertext": "1073, Almi",
"trans": [{
"account": "1510",
"amount": "52500.00"
}, {
"account": "3010",
"amount": "-42000.00"
}, {
"account": "2611",
"amount": "-10500.00"
}]
},
"A-2": {
"verdatum": "2016-07-08",
"vertext": "1074, Text",
"trans": [{
"account": "1510",
"amount": "15000.00"
}, {
"account": "3010",
"amount": "-12000.00"
}, {
"account": "2611",
"amount": "-3000.00"
}]
}
}
}
Code so far, but changes format of array
var newarray = [];
$.each(array["#VER"], function(i, item) {
if (condition for subarray) {
newarray.push(i,item);
}
});
You're working with an object here, not an array. This code should work:
var data = { ... }; // your original data object
var filteredData = filterData(data);
function filterData(data) {
var verData = data['#VER'];
var filteredVerData = {};
$.each(verData, function(key, value) {
if(value.vertext === '1073, Almi') { // your condition
filteredVerData[key] = value;
}
});
return {
'#VER': filteredVerData
};
}
But if you have many root keys like '#VER' and you need to filter all of them, you'd need to write one more loop:
var data = { ... }; // your original data object
var filteredData = filterData(data);
function filterData(data) {
var result = {};
$.each(data, function(verKey, verData) {
$.each(verData, function(aKey, aData) {
if(aData.vertext === '1073, Almi') { // your condition
result[verKey] = result[verKey] || {};
result[verKey][aKey] = aData;
}
});
});
return result;
}
I have an array of objects something like this
var data = [{"2017-09-13":{date_time:"2017-09-13",value:"20"}},{"2017-09-13":{date_time:"2017-09-13",value:"22"}},{"2017-09-15":{date_time:"2017-09-15",value:"25"}},{"2017-09-15":{date_time:"2017-09-15",value:"30"}},{"2017-09-16":{date_time:"2017-09-16",value:"10"}}];
I have an array of dates like this
var dates = ["2017-09-13","2017-09-15"];
I want to modify the data array in such a way that it only contains the days mentioned in the dates array. I have tried something like this
var date = [];
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < dates.length; j++) {
for (key in data[i]) {
if (dates[j] == key) {
date.push(data[i])
}
}
}
}
And it gives me the required result. However this is not efficient and is lagging the application. Is there any efficient way to go about it?
EDIT: Updated the correct data structure
const data = [
{
"2017-09-13": {
"date_time": "2017-09-13",
"value": "20"
}
},
{
"2017-09-13": {
"date_time": "2017-09-13",
"value": "22"
}
},
{
"2017-09-15": {
"date_time": "2017-09-15",
"value": "25"
}
},
{
"2017-09-15": {
"date_time": "2017-09-15",
"value": "30"
}
},
{
"2017-09-16": {
"date_time": "2017-09-16",
"value": "10"
}
}
];
const dates = ["2017-09-13", "2017-09-15"];
const datesSet = new Set(dates);
const filteredData = data.filter(item => datesSet.has(Object.keys(item)[0]));
console.log(filteredData);
Consider removing the use of dates as keys, as they seem to be redundant information:
const data = [
{
"date_time": "2017-09-13",
"value": "20"
},
{
"date_time": "2017-09-13",
"value": "22"
},
{
"date_time": "2017-09-15",
"value": "25"
},
{
"date_time": "2017-09-15",
"value": "30"
},
{
"date_time": "2017-09-16",
"value": "10"
}
];
const dates = ["2017-09-13", "2017-09-15"];
const datesSet = new Set(dates);
const filteredData = data.filter(item => datesSet.has(item.date_time));
console.log(filteredData);
Your datastructure is ugly. You will always need two loops to iterate it. However, we could set up a more elegant datastructure ( aka a Map), which we can access more easily:
const days = new Map();
for(const obj of data){
for(day in obj){
if( days.has(day) ){
days.get(day).push( obj[day] );
} else {
days.set(day, [ obj[day] ]);
}
}
}
After the Map is created, you can simply do:
days.get("2017-09-13")
to get an array of objects with datetime/values. That can be iterated easily:
days.get("2017-09-13").forEach( ({value}) => {
console.log(value);
});
Or getting multiple dates:
const result = new Map(
dates.map(date => [date, days.get( date )] )
);
console.log( [...result] );
and data only:
const result = [];
dates.forEach(date => result.push(...days.get(date)));
Here is a solution with only two for loops.
var data = [{'2017-09-13':{date_time:"2017-09-13",value:"20"}},{'2017-09-13':{date_time:"2017-09-13",value:"22"}},{'2017-09-15':{date_time:"2017-09-15",value:"25"}},{'2017-09-15':{date_time:"2017-09-15",value:"30"}},{'2017-09-16':{date_time:"2017-09-16",value:"10"}}];
var date = [];
for (var i = 0; i < data.length; i++) {
for (key in data[i]) {
if (date.indexOf(key) === -1) {
date.push(key);
}
}
}
console.log(date);
var dataByDate = { };
for (var i = 0; i < data.length; i++) {
for (var j in data[i])
dataByDate[j] = dataByDate[j] || true;
}
Converts the data to
{ '2017-09-13': true, '2017-09-15': true, '2017-09-16': true }
Then you can do
for (var i in dataByDate) { ... }
I have a quite complex data manipulation to perform.
My datasource gives me a list of cashflows, grouped by person like that:
{
"months": [
"2016-10-01",
"2016-11-01",
"2016-12-01",
"2017-01-01"
],
"persons": [
{
"label": "John",
"cashflows": [
{
"date": "2016-10-01",
"amount": "1000.00"
},
{
"date": "2016-11-01",
"amount": "1000.00"
}
]
},
{
"label": "Brad",
"cashflows": [
{
"date": "2017-01-01",
"amount": "5540.00"
}
]
}
]
}
I want to put those data in a DataTable, but I don't know how to "JOIN" the months and the cashflows.
My best guest is a sql-like query, but in javascript, in order to perform this pseudo-code:
select each person
for each person
good_row = person.cashflows LEFT JOIN months ON cashflows.date (iiish..)
I have set up a jsfiddle here.
Here is the plain javascript way to do it (the hard way).
Fiddle link: https://jsfiddle.net/ngwqfjo0/
function getDesiredData() {
var persons = real_data["persons"];
var months = real_data["months"];
persons.forEach(function(person) {
var row = [];
var amounts = [];
row.push(person["label"]);
months.forEach(function(month) {
var amount = '';
for(x = 0; x < person["cashflows"].length; x++) {
if(month == person["cashflows"][x]["date"]) {
amount = person["cashflows"][x]["amount"];
break;
}
}
amounts.push(amount);
});
desiredData.push(row.concat(amounts));
});
return desiredData;
}
To make life easier, consider using a functional utility like lodash or underscore
function getDesiredDataEasy() {
var persons = real_data["persons"];
var months = real_data["months"];
var desiredData = [];
return _.map(persons, function(person) {
return _.concat([person["label"]], _.map(months, function(month) {
var cashFlowDate = _.find(person["cashflows"], function(cf) {
return cf.date == month;
});
return cashFlowDate ? cashFlowDate.amount : "";
}));
});
}
How do I push an object into an specified array that only updates that array? My code pushes an object and updates all arrays, not just the specified one.
Here is the structure of the data:
{
"d": {
"results": [
{
"Id": 1,
"cost": "3",
"item": "Project 1",
"fiscalyear": "2014",
"reportmonth": "July"
}
]
}
}
Here is a sample of the desired, wanted results:
{
"Project 1": [
{
"date": "31-Jul-14",
"rating": "3"
},
{
"date": "31-Aug-14",
"rating": "4"
}
],
"Project 2": [
{
"date": "31-Jul-14",
"rating": "2"
}
]
}
This is my attempt:
var results = data.d.results;
var date;
var projectObj = {},
projectValues = {},
project = '';
var cost = '',
costStatus = '';
for (var i = 0, m = results.length; i < m; ++i) {
project = results[i]['item'];
if (!projectObj.hasOwnProperty(project)) {
projectObj[project] = [];
}
// use Moment to get and format date
date = moment(new Date(results[i]['reportmonth'] + ' 1,' + results[i]['fiscalyear'])).endOf('month').format('DD-MMM-YYYY');
// get cost for each unique project
costStatus = results[i]['cost'];
if (costStatus == null || costStatus == 'N/A') {
cost = 'N/A';
}
else {
cost = costStatus;
}
projectValues['rating'] = cost;
projectValues['date'] = date;
projectObj[project].push(projectValues);
}
Here is a Fiddle with the undesired, unwanted results:
https://jsfiddle.net/yh2134jn/4/
What am I doing wrong?
That is because You do not empty it new iteration. Try this:
for (var i = 0, m = results.length; i < m; ++i) {
projectValues = {};
project = results[i]['item'];
....
}
I got a json which looks like something like this :
var json = {
"stock1" : {
"positions" : [{
"date": "29/02/2016",
"price": 15,
"type": "short"
}]
},
"stock2" : {
"positions" : [{
"date": "29/02/2016",
"price": 20,
"type": "long"
}]
}
};
For the moment I have something like that :
<script>
function myFunction() {
;
}
</script>
<div id = "short">
<button onclick="myFunction()">
short
</button>
</div>
My json is actually bigger than this example. I'd like to loop through it to get only the positions who are "short" and print them.
What is the best way to do that using only javascript ?
EDIT :
This is my new code but I still can't access to short or long position :
var stocks = [];
var longOnMarket = [];
var shortOnMarket = [];
var typeOfPosition = [];
var lolz = [];
for (var key in json) {
if (json.hasOwnProperty(key)) {
var item = json[key];
lolz.push(JSON.stringify(item));
stocks.push(key);
var json2 = json[item];
for (var key2 in json2) {
if (json2.hasOwnProperty(key2)) {
var longOrShort = json2[key2].positions;
typeOfPosition.push(JSON.stringify(longOrShort));
}
}
}
}
alert(stocks);
alert(lolz);
alert(typeOfPosition);
What you can do is
var json = {
"stock1" : {
"positions" : [{
"date": "29/02/2016",
"price": 15,
"type": "short"
}]
},
"stock2" : {
"positions" : [{
"date": "29/02/2016",
"price": 20,
"type": "long"
}]
}
};
var object = JSON.parse(json);
for (var key in object) {
//Do your stuff
}
This solution looks for the array of positions and returns the object if some short is found.
var object = { "stock1": { "positions": [{ "date": "29/02/2016", "price": 15, "type": "short" }] }, "stock2": { "positions": [{ "date": "29/02/2016", "price": 20, "type": "long" }] } },
short = {};
Object.keys(object).forEach(function (k) {
if (object[k].positions.some(function (a) { return a.type === 'short' })) {
short[k] = object[k];
}
});
document.write('<pre>' + JSON.stringify(short, 0, 4) + '</pre>');
You should simple iterate through your object keys
var result = [];
for (var key in json) {
if (json.hasOwnProperty(key)) {
var item = json[key];
item.positions = item.positions.filter(function(el) { return el.type == 'short' });
result.push(item);
}
}
here is my try please check it out
var i,
shortTypePositionsArray = [],
shortTypeWholeObject = {};
$.each(json,function(key,value){
if(Object.keys(value) == "positions"){
for(i = 0;i<value.positions.length;i++){
if(value.positions[i].type == 'short')
{
shortTypePositionsArray.push(value.positions[i]);
shortTypeWholeObject[key] = value;
}
}
}
});
console.log(shortTypePositionsArray);
console.log(shortTypeWholeObject);