Convert an array into an object to create a report javascript - javascript

I have an array that represents a table like this:
table = [['john', 'male', 24, '12/12/12'], ['jane', 'female', 24, 12/12/12]]
I want to let the user choose which column they want, so later they can make a pdf report with the columns they chose, I think making an object like this is the best way to get that data, I might be wrong of course haha.
Let's say the user wants the following data on the report header: name, age, date, I want an object like this:
userHeader = { name: 'John', age: 24, date: '12/12/12'}
So I can make the next report:
Report #1234
|-------------------------------|
|Name: John Date: 24/12/12 | <-Header
|Age: 24 |
|-------------------------------|
|some data | <--Body
| .... |
|-------------------------------|
I have an array with the columns the user wants that stores it index, for example if the user wants the columns 1 and 2, the array is this:
var userColumns = [1,2]
How can I approach this problem? How would you do it?
EDIT: I put the wrong table,. this are the tables:
table1 = [['john', 'male', 24, '12/12/12', 1], ['john', 'male', 24, 01/05/12, 1]]
table2 = [['john', 'male', 24, '12/07/12', 2], ['john', 'male', 24, 05/05/12, 2]]
To get some context, I have a CSV file with multiple columns and rows, each row has a different codeItem, this codeItem can be repeated in multiple rows or not, what i do is create multiple tables that have the same code report, for example if the CSV data has 10 rows, 5 with an codeItem:1 and the other 5 with codeItem: 2, I create 2 tables, one with all the rows that have the codeItem 1 and another with a codeItem 2, then I would make a report for each codeItem, in this case 2 reports, so each table has some rows that have the same data on some columns.
The user columns is what columns the user chose to appear on the report, I have an array with the header columns:
var headers = ['name', 'sex', 'age', 'date', 'codeReport']
What I do is match the index on the header array to the userColumns, lets say the user wants the name and age headers, the user header is:
userHeader = [0, 2]
I know it sounds confusing and it really is.

First of all, if you want to use objects for storing data from an given array, you need I routine to convert them. Therefor I allways create an empty object o = {}, and with o["prop"] = value can this object be filled. The same as o.prop = value.
let headers = ['name', 'sex', 'age', 'date', 'codeReport'];
function createObjectFromArray(array, indexes)
{
let result = {};
for(let index of indexes)
{
result[headers[index]] = array[index];
}
return result;
}
let recordObject = createObjectFromArray(['john', 'male', 24, '12/12/12', 1], [1, 2]);
//Object {sex: "male", age: 24}
With the help of the ECMAScript 6 class Map, it is possible to link an object to any data. Or you can use IndexedDB.
let reportDataBase = new Map();
reportDataBase.set(recordObject, "somedata");
reportDataBase.get(recordObject); // "somedata"
If you want to iterate through all tables (table 1 has code item 1, table 2 has code item 2, ...), you need an object, which is iterable. I recommend an array.
let tables = [table1, table2];
let selectedColumns = [1, 2];
for(var report = 0; report != tables.length; report++)
{
console.log("report : " + (report + 1));
tables[report].forEach(function(item)
{
console.log(createObjectFromArray(item, selectedColumns));
});
}
I think a better way to storage in-memory data and generate different reports, is to use a data structure like this:
var reports = [
[['john', 24, "somedata1"], ['lara', 22, "somedata2"]],
[['mark', 21, "somedata3"], ['eve', 25, "somedata4"]]
];
But its a bad idea, to storage all personal data in a open browser. To much ressources for showing one record and the question is: Wants the person that his data is public?
One solution is: frontend <-> node.js

You just need an association of table headers with array of user data like
ReportHeaderAssociation = {
"0":Name",
"1":Age",
....
}
So when you got columns that users want( here [1,2] ) you can get title from association object and value by accessing array element.
Like , userdata[1] will give you second element from data which is gender. Likewise all elements.
In short: a single object with relativity will do the job no need to run long loops to convert array to object.

You need a mapping for the column names, for example with the same indexes as the data and a filter for which columns you want.
After that map and reduce are your friends ;)
var table = [
['John', 'male', 24, '12/12/12'],
['Jane', 'female', 22, '11/11/11']
];
var columnMapping = ['name', 'gender', 'age', 'date'];
var getData = function(data, columnNames, columnFilter) {
return data.map(function(item) {
return item.reduce(function(obj, item, idx) {
if (columnFilter.indexOf(idx) > -1) {
obj[columnNames[idx]] = item;
}
return obj;
}, {});
});
}
// age and gender
console.log(getData(table, columnMapping, [1, 2]));
// name and date
console.log(getData(table, columnMapping, [0, 3]));
// name, age and date
console.log(getData(table, columnMapping, [0, 2, 3]));
// name, age and date only if name is John
console.log(getData(table, columnMapping, [0, 2, 3]).filter(function(item) {
return item.name === 'John';
}));

Related

Create Table Based on Changing JSON Output

So to GET an output like this, I had to use some pretty cool tricks (see Analyzing Data from JSON in JavaScript). Please note my data in this example (# rows) is different.
var feeds = [].concat.apply([], dataSet_parsed.map(s => s.data));
//flattens arrays AGAIN to show all targets
var targets = [].concat.apply([], feeds.map(s => s.data));
//return target hits total
var targetList = targets.reduce(
function(prev, cur) {
var val = cur["val"];
prev[val] = ((prev[val] || 0) + 1);
return prev;
}, {});
// Output: {TargetA: 5, TargetB: 6, TargetC: 4, TargetD: 2}
Basically, I'm trying to get a count of how many times a target was seen per group. And fantastic! this works.
Here's my question. how do I display the output---
{TargetA: 5, TargetB: 6, TargetC: 4, TargetD: 2}
---in a table? There are no guarantees that I will always return the same TYPE of Targets (i.e. next load I could have:
{TargetK: 10, TargetL: 2, TargetM: 5, TargetN: 3, TargetO: 7, TargetP: 8}
I've tried using JSON.stringify and .replace() but I'm not getting very far. And even after that, I don't think I could style that output very well.
JSON.stringify(targetList).replace(/\}/g,'').replace(/\{/g,'')

Summarize & Group By with Lodash

I'm new to Lodash and I'm trying to perform a complex sum with group by as SQL but I don't find any solution. I have tried to use/combine multiple Lodash functions without success.
My requirement is like this. I have a JSON response:
input =
[{"quantity":1067,"gross_revenue":4094.2,"date":"03","company":"Cat1","product":"Car"},
{"quantity":106,"gross_revenue":409,"date":"02","company":"Cat2","product":"Car"},
{"quantity":106,"gross_revenue":85,"date":"03","company":"Cat2","product":"House"},
{"quantity":106,"gross_revenue":100,"date":"02","company":"Cat3","product":"House"},
{"quantity":20,"gross_revenue":150,"date":"03","company":"Cat5","product":"Technology"},
{"quantity":40,"gross_revenue":100,"date":"01","company":"Cat5","product":"Technology"},
{"quantity":20,"gross_revenue":15,"date":"01","company":"Cat5","product":"Car"},
{"quantity":20,"gross_revenue":18,"date":"01","company":"Cat5","product":"House"},
{"quantity":20,"gross_revenue":2,"date":"01","company":"Cat2","product":"House"},
{"quantity":20,"gross_revenue":25,"date":"01","company":"Cat3","product":"House"}]
I need to generate a result as below to populate the series for a HighChart:
[{ name: 'Car', data: [15, 409, 4094.2] },
{ name: 'House', data:[45, 100, 85] },
{ name: 'Techonology', data:[100, null, 150] }]
Those values are the result from:
Make a group by using Product with the tag name
Based on following procedure, generate an array with the tag data
2.1 Sum the gross revenue based on Product and date (all existing dates)
2.2 Include a null value if there doesn't exist gross revenue for any existing day
2.3 Sort the results for gross revenue based on date, ascending order
Is this possible? Or is there another solution for this?
Thanks.
Here's one way to do it - certainly not the only solution...
var input = [
{"quantity":1067,"gross_revenue":4094.2,"date":"03","company":"Cat1","product":"Car"},
{"quantity":106,"gross_revenue":409,"date":"02","company":"Cat2","product":"Car"},
{"quantity":106,"gross_revenue":85,"date":"03","company":"Cat2","product":"House"},
{"quantity":106,"gross_revenue":100,"date":"02","company":"Cat3","product":"House"},
{"quantity":20,"gross_revenue":150,"date":"03","company":"Cat5","product":"Technology"},
{"quantity":40,"gross_revenue":100,"date":"01","company":"Cat5","product":"Technology"},
{"quantity":20,"gross_revenue":15,"date":"01","company":"Cat5","product":"Car"},
{"quantity":20,"gross_revenue":18,"date":"01","company":"Cat5","product":"House"},
{"quantity":20,"gross_revenue":2,"date":"01","company":"Cat2","product":"House"},
{"quantity":20,"gross_revenue":25,"date":"01","company":"Cat3","product":"House"}
];
var result = [];
var groupedByProduct = _.groupBy(input, "product");
// get the set of unique dates
var dates = _.uniq(_.map(input, 'date'));
// for each product, perform the aggregation
_.forEach(groupedByProduct, function(value, key) {
// initialize the data array for each date
data = [];
for (var i = 0; i < dates.length; i++) {
data.push(null);
}
// aggregate gross_revenue by date
_.forEachRight(_.groupBy(groupedByProduct[key], "date"), function(dateValue, dateKey) {
// use the date as an array index
data[parseInt(dateKey) - 1] = _.sumBy(dateValue, function(o) {
return o.gross_revenue
});
});
// push into the result array
result.push({"name": key, "data": data});
});
document.getElementById("result").innerHTML = JSON.stringify(result);
<script src="https://cdn.jsdelivr.net/lodash/4.11.1/lodash.min.js"></script>
<pre id="result"></pre>

js: array with in an associative array

I am trying to set up an associative array for the following data:
name date alpha beta
Andrew 12/08/07 2.3 1.4
5/12/07
26/03/08
____________________________________
Fred 3/09/07 2.1 1.1
23/01/08
____________________________________
Basically, each patient would have a name and alpha , beta value but multiple dates on which they visited doctor. I was thinking of something like following where name is the primary key and dates are stored in an array and alpha, beta is a float value associated with the key.
var info = [{ name: [{ dates: [ ], alpha: float, beta: float }] }];
and then this info array would be populated on reading the csv file. What would be the right format for initialising such an associative array? or what other data structure would be a good approach for representing such a data?
Thanks in advance!
Edit: Since each patient has a unique name, instead of using an array, you should consider using a single object where each patient is an object identified by the object key, for example:
var patientList = {
andy: {},
bob: {}
};
To get your data from your CSV file into this structure you might consider something like this:
var csv = 'Andrew\t12/08/07\t1.2\t3.4\nAndrew\t15/09/08\t1.2\t3.4\nAndrew\t14/08/07\t1.2\t3.4\t\nBob\t18/09/08\t1.2\t3.4\nAndrew\t21/08/07\t1.2\t3.4\nDavid\t31/09/08\t1.2\t3.4\nAndrew\t22/08/07\t1.2\t3.4\t\nSam\t26/09/08\t1.2\t3.4';
// Split the CSV file at the carriage return.
var data = csv.split('\n');
// Recursive over the data with `map`, splitting each line up
// on the tabs and returning a patient object for each.
data = data.map(function (el) {
var patient = el.split('\t');
return {
name: patient[0],
date: patient[1],
alpha: patient[2],
beta: patient[3]
}
});
function getListOfPatientNames(arr) {
var newarr = [];
// For each patient object return the patient name only
newarr = arr.map(function (patient) {
return patient.name;
});
// A quick way of filtering out duplicates
return newarr.filter(function(elem, pos) {
return newarr.indexOf(elem) == pos;
});
}
// Return a unique list of names, and sort them.
var names = getListOfPatientNames(data).sort();
var patientList = {};
for (var i = 0, l = data.length; i < l; i++) {
var name = data[i].name;
// If the patient name doesn't exist in patientList yet
if (!patientList[name]) {
// Add a new patient object using the name as the key
var newPatient = {
dates: [data[i].date],
alpha: data[i].alpha,
beta: data[i].beta
};
patientList[name] = newPatient;
} else {
// If the patient already exists push the date to the dates array
patientList[name].dates.push(data[i].date);
}
}
Demo
The term "associative array" is almost never used wrt JavaScript; you use objects (sometimes called "maps" or "dictionaries") for name/value information, or arrays for ordered data.
It looks like you want an array of patient objects, like this:
var patients = [
{
name: "Andrew",
dates: [/*...the dates...*/],
alpha: 2.3,
beta: 1.4
},
{
name: "Fred",
dates: [/*...the dates...*/],
alpha: 2.1,
beta: 1.1
}
];
You might or might not want to use a constructor function to create those objects, depending on your needs, but with the simple data you've given there's probably no need.

How to define an empty javascript object with the following struture so that I can dynamically insert data into it?

I am using JIT Infovis stacked or mono-valued piechart to do some data visualization. The stacked pie chart takes an object "obj" specifically with the following structure:
This is the hard coded version of jsonObj:
var obj = {
// labelID is unique in each case and may be multiple or just one
'labelID': ['pVal'],
'values': [{ //labelName is unique in each case and will only be one
'labelName': 'name1',
//there may be multiple or just one "values"
//ex, 'values': [80, 40, 15, 10]
'values': 80
}, {
'labelName': 'name2',
'values': [20]
}, {
'labelName': 'name3',
'values': [38]
}, {
'labelName': 'name4',
'values': [58]
}]
};
I'm trying to dynamically populate "obj" with searched data returned to user. But I can not create an empty "obj" with the above specific structure to dynamically populate the data. I tried several times but don't think I'm creating them correctly.
I have three values that I'm trying to dynamically populate into this "obj" but can't get my arms around it. chartID[m], chartArrName[m], chartVal[m].
I need a correct empty "obj" that correspond to the structure defined above.
var "obj" = {
label: ['pVal'],
values: [{
label: [],
values: []
}]
};
for (m = 0; m <= chartArrID.length - 1; m++) {
obj.values[m].label += chartArrName[m];
obj.values[m].values += parseFloat(chartArrVal[m]);
//json.push({label: chartArrName[m], values: parseFloat(chartArrVal[m])});
}
This is not a JSON object. JSON is a lightweight data interchange format. You are just using a object initializer syntax to create an object. You can add what you want of the fly.
var myObj = {};
myObj.name = "foo";
myObj.books = [ "one", "two" ];
myObj.emptyField = null;
myObj.emptyArray = [];
myObj["anotherField"] = "bar"; // this works too
myObj.anotherArray = [];
myObj.anotherArray[0] = {}; // you need to insert something in the first position!
myObj.anotherArray[0].label = "aaa";
myObj.anotherArray[0].value = "bbb";
myObj.anotherArray[0].xyz = "ccc";
myObj.anotherArray[1] = {}; // in the second too, of course!
myObj.anotherArray[1].label = "ddd";
myObj.anotherArray[1].value = "eee";
myObj.anotherArray[1].xyz = "fff";

Adding items to a javascript array

I'm attempting to assign items to an array on a users action, so for example, user clicks "Add", this will add the selected id into the relevant section of the array.
The array won't be created at first so I set up an empty array:
var Options={};
On the users click, I then want to assign a key to match the option selected from a drop down so I can use this as a reference later on.
E.g. When the user clicks plus on a record, the option selected from a drop-down is 2. The id of the record they selected is say 5.
I'd like to structure my array like the following:-
[key e.g drop down option]
=> 'records' => array [record_id]
Each time the user clicks plus next to a record, the id is appended to the correct array based on the drop down selected option.
[option 1] => 'publication_date' = 12/09/2010, 'records' => [1, 2, 4]
[option 2] => 'publication_date' = 15/09/2010, 'records => [1, 3, 5]
etc, each option from the select box has a publication date and a series of records the user can assign to it.
You can do something like this:
function AddItem(key, value) {
if(Options[key]) Options[key].push(value);
else Options[key] = [value];
}
For example doing this:
​AddItem(2, 5);
AddItem(2, 6);
Would result in Options being:
{ 2: [5, 6] }
You can give it a try/play with it here.
An object in javascript is good to store a one key dataset not various keys.
ie:
var records = {'12/09/2010':[1, 2, 4], '15/09/2010':[1, 3, 5]}
To get the records for the 15/09: records['15/09/2010']
Add a new record for a date: records['15/09/2010'].push(6)
If the date change, you need to do something like:
records['17/09/2010'] = records['15/09/2010']; delete records['15/09/2010']
The user is not able to change both at the same time(date and add) and you should do both update actions separately.
Now if you plan to have more keys, you should use an array of objects:
var records = [
{publication_date:'12/09/2010', records:[1, 2, 4], ..., otherProp='...'},
...
];
And for each change, loop on the array, find the relevant item and change it.

Categories