I am currently trying to use morris.js to create a graph. I am given one JSON object and need to make it look like another. Morris.js needs an array to look like this
var day_data = [
{"period": "2012-10-01", "licensed": 3407, "sorned": 660},
{"period": "2012-09-17", "licensed": 3171, "sorned": 660},
{"period": "2012-09-16", "licensed": 3171, "sorned": 676},
{"period": "2012-09-15", "licensed": 3201, "sorned": 656},
{"period": "2012-09-10", "licensed": 3215, "sorned": 622}
];
here is the link if the object appears confusing. It should be a shortened version of the first graph's data on their site http://oesmith.github.com/morris.js/
. Its pretty simple, period is the x coordinate, and licensed and sorned are y coordinates for their corresponding lines.
Here is the data I am given
var trendline = {"command":[
{"keyValuePairs":["2012-08-10 22:00:00|1884978","2012-08-10 21:00:00|3135378","2012-08-10 18:00:00|2541438","2012-08-09 20:00:00|647082","2012-08-10 19:00:00|3194772","2012-08-09 16:00:00|2782140","2012-08-10 20:00:00|3669924"],
"keyword":"Obama"},
{"keyValuePairs":["2012-08-10 22:00:00|1884978","2012-08-10 21:00:00|3135378","2012-08-10 18:00:00|2541438","2012-08-09 20:00:00|647082","2012-08-10 19:00:00|3194772","2012-08-09 16:00:00|2782140","2012-08-10 20:00:00|3669924"],
"keyword":"Romney"}]}
I need to extract all the data from keyValuePairs and associate it with its keyword so looks like the first array
{"period": "2012-10-01", "Obama": 1884978, "Romney": 1884978},
...
...
I know to get the data from the trendline JSON object but i don't know how to construct a new JSON object that the morris.js plugin could use. More specifically i don't know how to create a JSON object using variables.
trendline.dog = [cat];
Will create a json object with the field dog set to the value cat. However, i need to take each keyword(obama,romney...etc) and have a field associated with it and set a value to it. Since i don't know the number of fields or what their names are, I don't know how to create this object.
Assume I cannot change the way I am given data as I do not write that part. Also I could be given only two keywords (obama/romney) like in my example or i could be given any number of keywords for the y-values.
Sorry for the long length. Any help would be appreciated. Thanks for your time.
Here is your Christmas present.
<script type="text/javascript">
var trendline =
{
"command": [
{
"keyValuePairs":
[
"2012-08-10 22:00:00|1884978",
"2012-08-10 21:00:00|3135378",
"2012-08-10 18:00:00|2541438",
"2012-08-09 20:00:00|647082",
"2012-08-10 19:00:00|3194772",
"2012-08-09 16:00:00|2782140",
"2012-08-10 20:00:00|3669924"
],
"keyword": "Obama"
},
{
"keyValuePairs":
[
"2012-08-10 22:00:00|1884978",
"2012-08-10 21:00:00|3135378",
"2012-08-10 18:00:00|2541438",
"2012-08-09 20:00:00|647082",
"2012-08-10 19:00:00|3194772",
"2012-08-09 16:00:00|2782140",
"2012-08-10 20:00:00|3669924"
],
"keyword": "Romney"
}]
}
var cmd = trendline.command,
day_data = [],
split,
date,
num,
obj;
//
for (var i = 0; i < cmd.length; i++) {
//
if (i == 1) { break; };
//
for (var ii = 0; ii < cmd[i].keyValuePairs.length; ii++) {
//debugger
split = cmd[i].keyValuePairs[ii].split('|');
date = split[0].substring(0, split[0].indexOf(' '));
num = split[1];
obj = {};
obj['period'] = date;
//Can 1
obj[cmd[i].keyword] = num;
//
split = cmd[i + 1].keyValuePairs[ii].split('|');
num = split[1];
//Can 2
obj[cmd[i + 1].keyword] = num;
//
day_data.push(obj);
};
};
Related
I have been able to export data from google sheets into a pretty awesome JSON file, just not in the format I need (oops:) ).
Basically, I have data where the column name is the value header (in this case: location, infected, deaths, recovered, etc.) and row name are the values respectively.
Is there a way I can reformat this into multiple objects so I have:
var death_data = {
cn: "132",
th: "0",
mo: "0",
au: "0",
sg: "0",
};
var infected_data = {
cn: "4415",
th: "8",
mo: "7",
au: "5",
sg: "5",
};
(The 2 letters are the Country Codes. CN: 3554+277+296+..other china values+...152+108+84...+13+6.)(132=125+2+1+1+1+1+1)
I found a similar resource here, however it is in R. Is there a similar method for JavaScript?
In case your wondering how I have tried to generate the objects:
function doGet() {
var result = {};
var infected = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data').getDataRange().getValues();
var death = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data').getDataRange().getValues();
result = makeObject(infected);
// result.death = makeObject(death);
//Logger.log(result);
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}
function makeObject(multiArr) {
var obj = {};
var headers = multiArr.shift();
for(var i = 0; i < headers.length; i++){
obj[headers[i]] = multiArr.map(function(app) {
return app[i];
});
}
return obj;
}
Using the above code, the JSON looks like this (Using JSON Viewer chrome extension):
Where each key then has values, like this:
and this
Maybe there is a better way than trying to convert the formats after the fact, and instead just generate them correctly the first time.
Sorry in advance for my basic knowledge of JavaScript, i'm just getting started.
Any help would be greatly appreciated.
Kind Regards,
Camden
You could create such a object by looping over the array and adding relevant values:
Sample script:
function makeObject(multiArr) {
var obj = {deaths:{}, infected:{}};
var headers = multiArr.shift();
multiArr.forEach(function(row){
var [_,country,_,infected,deaths,_] = row;
obj.deaths[country] = obj.deaths[country] || 0;
obj.infected[country] = obj.infected[country] || 0;
obj.deaths[country] = obj.deaths[country] + Number(deaths);
obj.infected[country] = obj.infected[country] + Number(infected);
})
return obj;
}
I am trying to write a very simple implementation of the Towers of Hanoi puzzle to practice what I have just learned about js constructors and prototypes. I am currently having problems with what I have written so far because every time I move a 'disc' from tower[0] to let's say tower[1], my tower[2] also gets updated with the same disc. Also, when I try to make an invalid move, I still get the disc I tried to move, taken away from its tower. I have checked out my logic and I can't see anything wrong with it (I could be just biased at this point too). I am wondering if it is a problem with my constructor function or any of my methods?
Here my code :
function TowersOfHanoi(numberOfTowers){
let towersQuant = numberOfTowers || 3 , towers;
towers = Array(towersQuant).fill([]);
towers[0] = Array(towersQuant).fill(towersQuant).map((discNumber, idx) => discNumber - idx);
this.towers = towers;
}
TowersOfHanoi.prototype.displayTowers = function(){
return this.towers;
}
TowersOfHanoi.prototype.moveDisc = function(fromTower,toTower){
let disc = this.towers[fromTower].pop();
if(this.isValidMove(disc,toTower)){
this.towers[toTower].push(disc);
return 'disc moved!'
} else {
return 'disc couldn\'t be moved.'
}
}
TowersOfHanoi.prototype.isValidMove = function(disc,toTower){
if(this.towers[toTower][toTower.length-1] > disc || this.towers[toTower].length === 0){
return true;
}else {
return false;
}
}
this is what I am testing :
let game2 = new TowersOfHanoi();
console.log(game2.displayTowers());
console.log(game2.moveDisc(0,1));
console.log(game2.displayTowers());
console.log(game2.moveDisc(0, 2));
console.log(game2.displayTowers());
and my output :
[ [ 3, 2, 1 ], [], [] ]
disc moved!
[ [ 3, 2 ], [ 1 ], [ 1 ] ]
disc couldn't be moved.
[ [ 3 ], [ 1 ],[ 1 ] ]
I appreciate any guidance. I am not necessarily looking for code. just to understand. Thanks
This quote from the Array fill() documentation tells you the problem:
When the fill method gets passed an object, it will copy the reference and fill the array with references to that object.
towers = Array(towersQuant).fill([]);
Arrays are objects. So what you've done is copy a reference of the first Array to each of the other arrays. The whole thing is compounded when you iterate these references to modify them.
Update
Something like this will work:
function TowersOfHanoi(numberOfTowers){
let towersQuant = numberOfTowers || 3 , towers = [];
for(let i=1; i < towersQuant; i++){
towers.push([]);
towers[0].push(i);
}
towers[0].reverse();
this.towers = towers;
}
I have the following JSON tree:
[
{
"category":"PASTAS",
"createdAt":"2016-01-01T19:47:57.813Z",
"currency":"$",
"dishName":"Spaghetti",
"estTime":"10-20 min",
"price":10,
"subName":"Pasta",
"updatedAt":"2016-04-28T20:48:06.800Z"
},
{
"category":"PIZZAS",
"createdAt":"2016-04-19T21:44:56.285Z",
"currency":"$",
"dishName":"Ai Funghi Pizza ",
"estTime":"20-30 min",
"price":20,
"subName":"Pizza",
"updatedAt":"2016-04-28T20:58:39.499Z"
},
{
"category":"PIZZAS",
"createdAt":"2016-04-19T21:44:56.285Z",
"currency":"$",
"dishName":"Seafood Pizza",
"estTime":"20-30 min",
"price":10,
"subName":"Pizza",
"updatedAt":"2016-04-28T20:58:39.499Z"
}
]
As you can see in the JSON tree the element category:"PIZZAS" repeats two times, what I would like to do is to either create a new array or organize these results in a way to avoid repetition in all the other duplicates, i.e. in the example above, I would have a final results like this:
Pastas:
Spaghetti
Pizza:
Ai Fungi Pizza,
Seafood Pizza
Any ideas on how to achieve the wanted result?
Assuming the array is named data, this should do the trick:
var result = {}; // Create an output object.
for(var i = 0; i < data.length; i++){ // Loop over the input array.
var row = data[i]; // Store the current row for convenience.
result[row.category] = result[row.category] || []; // Make sure the current category exists on the output.
result[row.category].push(row.dishName); // Add the current dish to the output.
}
lodash#groupBy is exactly what you want.
lodash.groupBy(foods, function(food) { return food.category; });
Here's an example with your JSON:
http://codepen.io/damongant/pen/xVQBXG
How would you go about getting all inventory locations for a particular item? What I would like is to check if a specific inventory location has any allotted inventory for an item.
I have tried to use the nlapiSearchRecord('item',null,filter,columns) to try this but it only returns the preferred location and not all locations even though their is inventory in the other locations.
Filters were setup as such:
filters = [ new nlobjSearchFilter('internalid',null,'is',10)];
If I add new nlobjSearchFilter('location',null,'is',34) to the filters which is the id for the inventory location I am looking for, I don't get any results at all.
the return I get from the above filters only list the preferred location and not any other locations with available inventory.
-- UPDATE --
After updating the code to use the suggestion below I am now getting the inventory location but not the correct inventory count for the location which should be 5 not 87
var itemId = 3376;
var locationId = 34;
var items = [];
var filters = [];
var columns = [];
filters = [
new nlobjSearchFilter('internalid',null,'is',itemId),
new nlobjSearchFilter('inventorylocation',null,'is',locationId),
new nlobjSearchFilter('quantityavailable',null,'greaterthan',0)
];
columns = [
new nlobjSearchColumn('itemid'),
new nlobjSearchColumn('inventorylocation'),
new nlobjSearchColumn('quantityavailable'),
new nlobjSearchColumn('quantityonhand'),
];
var results = nlapiSearchRecord('item',null,filters,columns);
if (results != null)
{
for (var i=0, l=results.length; i < l; i++)
{
var result = results[i];
items.push(result);
}
}
OUT PUT printed in JSON Format
{
"id": "3376",
"recordtype": "assemblyitem",
"columns": {
"itemid": "Marketing : Misc : T-Shirt Womens Medium",
"inventorylocation": {
"name": "InventoryLocation",
"internalid": "34"
},
"quantityavailable": 87,
"quantityonhand": 90
}
}
Thanks in advance.
I believe the field to use is the 'inventorylocation' field.
You should use the locationquantityavailable and locationquantityonhand columns instead of the ones you are using.
For references to the available columns/fields on a records, you may lookup the "Records Browser" in Help.
I am working to fetch and analyze a large data set.
I want to know how many each value is appearing in the data set.
Let's give a small example to clarify things.
[
{"Year": "1997", "Company": "Ford", "Model": "E350", "Length": "2.34"},
{"Year": "2000", "Company": "Mercury", "Model": "Cougar", "Length": "2.38"}
{"Year": "2001", "Company": "Ford", "Model": "Cougar", "Length": "2.38"}
]
I don't know exactly what the values that I am having, but I want to hash it to get the results this way.
[
{"Value": "Ford", "Frequency": 2},
{"Value": "Mercury", "Frequency": 1},
]
In case it's not dynamic and I know the the values, I will do it this way:
var filteredCompany = data.filter(function(a) {
return /Ford/i.test(a.Company).lenght;
});
But, I have a very large data set (900 Mbo), I need to make this process in a very dynamic way.
UPDATE
var dataset = {}
d3.csv(link, function(data) {
dataset = data;
});
//Fetch data
var frequency = {};
var datasetlength = dataset.length;
for(var i = 0; i < datasetlength; i++){
var current = dataset[i];
if(!frequency.hasOwnProperty(current.company)) frequency[current.company] = 0;
frequency[current.company]++;
}
What you can do is loop through all the entries, and gather them into an object where the key is the name and the value is the count. The initial data will look like this:
{
"Ford" : 2,
"Mercury" : 1
}
You can do a reduce, passing through an object:
var frequency = hugeData.reduce(function(freq,current){
var currentCompany = current.Company;
if(!freq.hasOwnProperty(currentCompany)) freq[currentCompany] = 0;
freq[currentCompany]++;
return freq;
},{});
But reduce is ES5 and sometimes slow. You can do a plain loop:
var frequency = {};
var hugeDataLength = hugeData.length;
for(var i = 0; i < hugeDataLength; i++){
var current = hugeData[i];
var currentCompany = current.Company;
if(!frequency.hasOwnProperty(currentCompany)) frequency[currentCompany] = 0;
frequency[currentCompany]++;
}
Now that we have reduced the data into a much more manageable size, you can loop through the frequency data and turn it into an array, moving down the key and value into an object.
var chartData = Object.keys(frequency).map(function(company){
var value = frequency[company];
return {
Value : company,
Frequency : value
}
});
A running demo can be seen here.
I did a similar feat in the past few months, and your browser's debugger is a very handy tool for this job, especially the CPU profiler. You can pin down which operations are actually causing the lag.
I'm not sure if this is the most efficient method of going through that much data (then again, Javascript was not made for big data so efficiency shouldn't be on your mind).
Basically I would approach this looping through all the data with an associative array keeping track of the frequency. If the current data.Company is not in the associative array, it'll add it on to the array as a key and then input the frequency of one. If it is found as a key in the array, it'll increment the frequency by 1.
Example