I have received a JSON response like
[
{"no":001, "location": "England", "year":"2017", "month":"4", "amount":"1000"},
{"no":002, "location": "Italy", "year":"2017", "month":"3", "amount":"8000"},
{"no":001, "location": "England", "year":"2016", "month":"2", "amount":"9000"},
{"no":001, "location": "England", "year":"2016", "month":"11","amount":"12000"}
];
I need to make it
[
{"no":001, "location": "England", "year":"2016", "amount2":"9000", "amount11":"12000"},
{"no":001, "location": "England", "year":"2017", "amount4":"1000"},
{"no":002, "location": "Italy", "year":"2017", "amount3":"8000"}
];
that is based on the no converting multiple records to one with amounts specific to months and common info ie location but same no should have different records corresponding to the year.
General advice: Collect the information by ID in another datastructure. I suppose this is an Accumulator Pattern.
var rows = [
{"no":"001","month":"4","amount":"1000"},
{"no":"002","month":"3","amount":"8000"},
{"no":"001","month":"2","amount":"9000"},
{"no":"001","month":"11","amount":"12000"}
];
var results = [];
var idToResultsObject = {};
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var id = row['no'];
if (typeof idToResultsObject[id] == 'undefined')
idToResultsObject[id] = { 'no' : id };
idToResultsObject[id]['location'] = row['location'];
idToResultsObject[id]['amount' + row['month']] = row['amount'];
}
for (var id in idToResultsObject) {
results.push(idToResultsObject[id]);
}
console.log(results);
Surely there is a nicer way to store this.
Here is updated es5 code to match your latest edit of the question:
(I'm still not sure I understand what you want from no so for now I leave it as number which it is in input (not in quotes)
var input = [
{"no":001, "location": "England", "year":"2017", "month":"4", "amount":"1000"},
{"no":002, "location": "Italy", "year":"2017", "month":"3", "amount":"8000"},
{"no":001, "location": "England", "year":"2016", "month":"2", "amount":"9000"},
{"no":001, "location": "England", "year":"2016", "month":"11","amount":"12000"}
];
/*
[
{"no":001, "location": "England", "year":"2016", "amount2":"9000", "amount11":"12000"},
{"no":001, "location": "England", "year":"2017", "amount4":"1000"},
{"no":002, "location": "Italy", "year":"2017", "amount3":"8000"}
];
*/
var output = input.reduce( function(result, cur) {
var ref = result.find( function(row) {
return row.no === cur.no && row.location === cur.location && cur.year === row.year }
);
if (ref) {
ref["amount"+cur.month] = cur.amount;
} else {
var newRow = { "no": cur.no, "location": cur.location, "year": cur.year };
newRow["amount"+cur.month] = cur.amount;
result.push(newRow);
}
return result;
},[])
console.log(output);
As others have suggested, it's really a bad way to design those objects. But this code does what you want (es6 syntax):
var input = [
{"no":001,"month":"4","amount":"1000"},
{"no":002,"month":"3","amount":"8000"},
{"no":001,"month":"2","amount":"9000"},
{"no":001,"month":"11","amount":"12000"}
];
/*
[
{"no":001, "amount2":"9000", "amount4":"1000", "amount11":"12000"},
{"no":002, "amount3":"8000"}
];
*/
var output = input.reduce( (result, cur) => {
var ref = result.find( row => row.no === cur.no);
if (ref) {
ref["amount"+cur.month] = cur.amount;
} else {
var newRow = { "no": cur.no };
newRow["amount"+cur.month] = cur.amount;
result.push(newRow);
}
return result;
},[])
console.log(output);
es5 syntax
var input = [
{"no":001,"month":"4","amount":"1000"},
{"no":002,"month":"3","amount":"8000"},
{"no":001,"month":"2","amount":"9000"},
{"no":001,"month":"11","amount":"12000"}
];
/*
[
{"no":001, "amount2":"9000", "amount4":"1000", "amount11":"12000"},
{"no":002, "amount3":"8000"}
];
*/
var output = input.reduce( function(result, cur) {
var ref = result.find( function(row) { return row.no === cur.no });
if (ref) {
ref["amount"+cur.month] = cur.amount;
} else {
var newRow = { "no": cur.no };
newRow["amount"+cur.month] = cur.amount;
result.push(newRow);
}
return result;
},[])
console.log(output);
Related
If I have a two dimensional array with each array containing objects, how would I search to see if a value exists on the object and if it does return the index of the array?
Basic array defined
`
DB = [
[
{
venue_country : "Denmark",
venue_city : "Copenhagan"
},
{
venue_country : "Italy",
venue_city : "Pisa"
}
],
[
{
venue_country : "UK",
venue_city : "London"
},
{
venue_country : "Spain",
venue_city : "Madrid"
},
{
// Exists Here;
venue_country : "Brazil",
venue_city : "Rio"
},
{
venue_country : "USA",
venue_city : "New York"
}
]
]
`
In the example how would I search the array to see if the venue_city "Rio" exists, if it does return the index, in this case it exists here at DB[1][2].venue_city so a value would return (1,2) otherwise if nothing is found a null value would be returned.
I know how I can do it with a standard object but not in the scenario outlined.
You could use nested Array.prototype.findIndex and return an array like [1,2], or [-1,-1] if not found:
const DB = [
[
{venue_country: "Denmark", venue_city: "Copenhagan"},
{venue_country: "Italy", venue_city: "Pisa"},
],
[
{venue_country: "UK", venue_city: "London"},
{venue_country: "Spain", venue_city: "Madrid"},
{venue_country: "Brazil", venue_city: "Rio"},
{venue_country: "USA", venue_city: "New York"},
]
];
const findVenueIndex = (prop, val) => {
let idxItem = -1;
const idxParent = DB.findIndex((arr) => {
idxItem = arr.findIndex((ob) => ob[prop] === val);
return idxItem > -1;
});
return [idxParent, idxItem];
};
console.log(findVenueIndex("venue_city", "Rio"));
console.log(findVenueIndex("venue_city", "Zagreb"));
Please iterate the array.
let result = null;
DB.forEach((subArray, i) => {
subArray.forEach((item, j) => {
if('Rio' === item.venue_city) {
result = {i, j};
}
});
});
console.log(JSON.stringify(result));
The output will be like this.
{"i":1,"j":2}
const linearSearch = (arr, target) => {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (Object.keys(arr[i][j]).indexOf(target.key) && arr[i][j][target.key] === target.value) {
return [i, j];
}
}
}
return null;
}
let arr = [[
{
venue_country: "Denmark",
venue_city: "Copenhagan"
},
{
venue_country: "Italy",
venue_city: "Pisa"
}
], [
{
venue_country: "UK",
venue_city: "London"
},
{
venue_country: "Spain",
venue_city: "Madrid"
},
{
venue_country: "Brazil",
venue_city: "Rio"
},
{
venue_country: "USA",
venue_city: "New York"
}
]];
// target: {key: string, value: string}
let target = {key: 'venue_city', value: 'Rio'};
let ans = linearSearch(arr, target);
console.log(`Element found at index: `, ans);
There is a JSON data and I have displayed each key value as a column in the table.
I want to export data from JSON to each column as a selectbox.
i.e. I want to show all corresponding values of "country" in JSON as selectbox in COUNTRY column.
My JSON data
"kitap": [
{
"author": "Chinua Achebe",
"country": "Nigeria",
"imageLink": "images/things-fall-apart.jpg",
"language": "English",
"link": "https://en.wikipedia.org/wiki/Things_Fall_Apart\n",
"pages": 209,
"title": "Things Fall Apart",
"year": 1958
},
{
"author": "Hans Christian Andersen",
"country": "Denmark",
"imageLink": "images/fairy-tales.jpg",
"language": "Danish",
"link": "https://en.wikipedia.org/wiki/Fairy_Tales_Told_for_Children._First_Collection.\n",
"pages": 784,
"title": "Fairy tales",
"year": 1836
},
My Javascript
let table2 = document.getElementById("tr2")
var books = fetch("kitap.json")
.then(res=> res.json())
.then(veri => {for(let data in veri ) {
for(deger of veri[data]) {
select.innerHTML+= `
<td><option value="${deger.author}">${deger.author}</option></td>
<td><option value="${deger.country}">${deger.country}</option></td>
`
}
}})
How can i edit?
Do you mean something like this? A loop over the keys, then a loop for all the items for each key. Finally after aggregating into array, we do a <select> element using a simple utility function.
var obj = {"kitap":[{"author":"Chinua Achebe","country":"Nigeria","imageLink":"images\/things-fall-apart.jpg","language":"English","link":"https:\/\/en.wikipedia.org\/wiki\/Things_Fall_Apart\n","pages":209,"title":"Things Fall Apart","year":1958},{"author":"Hans Christian Andersen","country":"Denmark","imageLink":"images\/fairy-tales.jpg","language":"Danish","link":"https:\/\/en.wikipedia.org\/wiki\/Fairy_Tales_Told_for_Children._First_Collection.\n","pages":784,"title":"Fairy tales","year":1836}]}
function do_select(select, options, name) {
select.innerHTML = '<option>Choose ' + name + '</options>';
options.forEach(function(value) {
var z = document.createElement("option");
z.setAttribute("value", value);
z.innerText = value;
select.appendChild(z)
})
}
do_obj_selects(obj)
function do_obj_selects(obj) {
var arr = obj.kitap;
var keys = Object.keys(obj.kitap[0]);
var result = {}
keys.forEach(function(key) {
obj.kitap.forEach(function(item) {
result[key] = result[key] || []
result[key].push(item[key])
})
var sel_category = document.createElement("SELECT");
sel_category.setAttribute("id", "category");
document.body.appendChild(sel_category);
do_select(sel_category, result[key], key)
})
}
I have an object that looks like below
const tableData = [
{
"Location": "London",
"Status": "Unknown"
},
{
"Location": "Delhi",
"Status": "Reachable"
},
{
"Location": "Berlin",
"Status": "Unknown"
},
{
"Location": "Tokyo",
"Status": "Busy"
},
]
Now I want to create a 2D array which will hold this information in a certain way. Here is my code below
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
let statusOrderInfo = Array(Object.keys(statusOrder).length).fill([]);
for(let i=0; i< tableData.length; i++) {
const status = tableData[i]["Status"].trim()
const statusIndex = statusOrder[status]
statusOrderInfo[statusIndex].push(tableData[i])
}
console.log(statusOrderInfo)
As you can see I want each item of the tableData object to be in a certain index of the 2D array. So the item that contains Status as Reachable should be at index 0, the item that contains the Status as Busy should be at index 1 and so on.
So the final output should look like
[
[
{
"Location":"Delhi",
"Status":"Reachable"
}
],
[
{
"Location":"Tokyo",
"Status":"Busy"
}
],
[
{
"Location":"London",
"Status":"Unknown"
},
{
"Location":"Berlin",
"Status":"Unknown"
}
]
]
But I get a wrong output on running the above code even though I am targeting the correct index. What's wrong in my approach?
Using Array#reduce:
const
tableData = [ { "Location": "London", "Status": "Unknown" }, { "Location": "Delhi", "Status": "Reachable" }, { "Location": "Berlin", "Status": "Unknown" }, { "Location": "Tokyo", "Status": "Busy" } ],
statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2};
const statusOrderInfo = tableData.reduce((list, e) => {
const index = statusOrder[e.Status];
list[index] = [...(list[index] || []), {...e}];
return list;
}, []);
console.log(statusOrderInfo);
Simple fix on your problem is that just changing your manner to set initial value of statusOrderInfo and use Array.from instead of Array.fill like this:
let statusOrderInfo = Array.from({length: Object.keys(statusOrder).length}, ()=> []);
another solution is set initiali value of statusOrderInfo by empty array, and then in your for loop, after you get the index of current object based on status value, you can check if statusIndex already exist in the statusOrderInfo or not, like this:
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
let statusOrderInfo = [];
for(let i=0; i< tableData.length; i++) {
const status = tableData[i]["Status"].trim()
const statusIndex = statusOrder[status];
if(statusOrderInfo[statusIndex]) statusOrderInfo[statusIndex].push(tableData[i]);
else statusOrderInfo[statusIndex] = [ tableData[i] ]
}
console.log(statusOrderInfo);
another solution, is to use reduce method on array, like this:
const tableData = [{
"Location": "London",
"Status": "Unknown"
},
{
"Location": "Delhi",
"Status": "Reachable"
},
{
"Location": "Berlin",
"Status": "Unknown"
},
{
"Location": "Tokyo",
"Status": "Busy"
},
];
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
const result = tableData.reduce((acc, cur) => {
const index = statusOrder[cur.Status];
if (acc[index]) acc[index].push(cur);
else acc[index] = [cur]
return acc;
}, []);
console.log(result)
Anoter one solution in kind of declartive way:
First of all sort objects by status code using Array#sort
And then just wrap every object to it own array using Array#map
const tableData = [{Location: "London",Status: "Unknown"},{Location: "Delhi",Status: "Reachable"},{Location: "Berlin",Status: "Unknown"},{Location: "Tokyo",Status: "Busy"}]
const statusOrder = {Reachable: 0, Busy: 1, Unknown: 2}
const result = tableData
.sort(({ Status: s1 }, { Status: s2 }) => statusOrder[s1] - statusOrder[s2])
.map((item) => [item]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
As others explained, reduce would be the best choice for your scenario. Because on every iteration you would create a new Array object.
const tableData = [{ Location: "London", Status: "Unknown" }, { Location: "Delhi", Status: "Reachable" }, { Location: "Berlin", Status: "Unknown" }, { Location: "Tokyo", Status: "Busy" }]
const statusOrder = { "Reachable": 0, "Busy": 1, "Unknown": 2 };
const statusOrderInfo = tableData.reduce((accumulator, currentValue) => {
const index = statusOrder[currentValue.Status];
if (accumulator[index]) {
accumulator[index].push(currentValue);
} else {
accumulator[index] = [currentValue];
}
return accumulator;
}, []);
console.log(statusOrderInfo);
Explanation for what's going on in your code:
As you have used [].fill([]) to fill the Array. It would create only one empty Array object and use it to initialize the actual array. That's why the following snippet behaves the way it should behave :)
const statusOrderInfo = Array(3).fill([]);
statusOrderInfo[0].push(10);
console.log(statusOrderInfo);
/* Results:
[
[ 10 ],
[ 10 ],
[ 10 ]
]
*/
this is my solution:
let statuses = ["Reachable", "Busy", "Unknown"];
const tableData = [
{"Location": "London", "Status": "Unknown"},
{"Location": "Delhi", "Status": "Reachable" },
{"Location": "Berlin", "Status": "Unknown"},
{"Location": "Tokyo", "Status": "Busy"}
];
let result = statuses.map(status => tableData.filter(tableDataItem => tableDataItem.Status == status));
console.log(result);
I am working in angularjs. i am getting a response in json format. and the json is
"vals": [{
"season": "SUMMER",
"usage": [
["PEAK", "1.000", "2.000", "3.000", "4.000", "5.000", "6.000", "7.000", "8.000", "9.000"],
["NORMAL", "10.000", "11.000", "12.000", "13.000", "14.000", "25.000", "16.000", "17.000", "18.000"],
["OFF-PEAK", "19.000", "20.000", "21.000", "22.000", "23.000", "24.000", "25.000", "26.000", "27.000"]
]
}, {
"season": "MONSOON",
"usage": [
["PEAK", "28.000", "29.000", "30.000", "31.000", "32.000", "33.000", "34.000", "35.000", "36.000"],
["NORMAL", "37.000", "38.000", "39.000", "40.000", "41.000", "42.000", "43.000", "44.000", "45.000"],
["OFF-PEAK", "46.000", "47.000", "48.000", "49.000", "50.000", "51.000", "52.000", "53.000", "54.000"]
]
}, {
"season": "WINTER",
"usage": [
["PEAK", "55.000", "56.000", "57.000", "58.000", "58.000", "59.000", "60.000", "61.000", "62.000"],
["NORMAL", "63.000", "64.000", "65.000", "66.000", "67.000", "68.000", "69.000", "70.000", "71.000"],
["OFF-PEAK", "72.000", "73.000", "74.000", "75.000", "76.000", "77.000", "78.000", "79.000", "80.000"]
]
}]
I have to calculate the value of each column and push that into a new array i.e
[(1.000+10.000+19.000+28.000+37.000+46.000+55.000+63.000+72.000),(2.000+11.000+20.000+29.000+38.000+47.000+56.000+64.000+73.000),(3.000+12.000+21.000+30.000+39.000+48.000+57.000+65.000+74.000),(4.000+13.000+22.000+31.000+40.000+49.000+58.000+66.000+75.000).....]
I was doing that and got the desire result but i mention the column number when i am calculating the total but column can be dynamic. I was ashamed to say that i was unable to solve it. If there is any way to make it dynamic please help. or if there is any better way then please share. I worked for 5 columns but given json has 9 columns. My code is
$scope.ctrlFn= function(){
var raw = angular.copy($scope.subStationsData);
var calcArray = raw.vals;
$scope.grossEnergy = raw.vals;
var k1Array = [];
var k2Array = [];
var k3Array = [];
var k4Array = [];
var k5Array = [];
$scope.totalArray = [];
function getSum(total, num) {
return total + num;
}
for (var i=0; i<calcArray.length; i++) {
for (var j=0; j<(calcArray[i].usage.length)-1; j++){
for (var k = 1; k < calcArray[i].usage[j].length; k++) {
console.log('j', j)
console.log('k', k)
console.log('calcArray[j].usage[k]: ',calcArray[i].usage[j][k]);
if(k==1){
k1Array.push(calcArray[i].usage[j][k]);
console.log('k1Array: ',k1Array);
}
if(k==2){
k2Array.push(calcArray[i].usage[j][k]);
console.log('k1Array: ',k2Array);
}
if(k==3){
k3Array.push(calcArray[i].usage[j][k]);
console.log('k1Array: ',k3Array);
}
if(k==4){
k4Array.push(calcArray[i].usage[j][k]);
console.log('k1Array: ',k4Array);
}
if(k==5){
k5Array.push(calcArray[i].usage[j][k]);
console.log('k1Array: ',k5Array);
}
}
}
}
var col1 = k1Array.map(Number).reduce(getSum);
var col2 = k2Array.map(Number).reduce(getSum);
var col3 = k3Array.map(Number).reduce(getSum);
var col4 = k4Array.map(Number).reduce(getSum);
var col5 = k5Array.map(Number).reduce(getSum);
$scope.totalArray.push(col1);
$scope.totalArray.push(col2);
$scope.totalArray.push(col3);
$scope.totalArray.push(col4);
$scope.totalArray.push(col5);
console.log('totalArray: ',$scope.totalArray);
$scope.$apply();
}
You can use array#reduce to hold each sum of the column and iterate each array using array#forEach.
var data = {"vals": [{ "season": "SUMMER", "usage": [ ["PEAK", "1.000", "2.000", "3.000", "4.000", "5.000", "6.000", "7.000", "8.000", "9.000"], ["NORMAL", "10.000", "11.000", "12.000", "13.000", "14.000", "25.000", "16.000", "17.000", "18.000"], ["OFF-PEAK","19.000", "20.000", "21.000", "22.000", "23.000", "24.000", "25.000", "26.000", "27.000"] ] }, { "season": "MONSOON", "usage": [ ["PEAK", "28.000", "29.000", "30.000", "31.000", "32.000", "33.000", "34.000", "35.000", "36.000"], ["NORMAL", "37.000", "38.000","39.000", "40.000", "41.000", "42.000", "43.000", "44.000", "45.000"], ["OFF-PEAK", "46.000", "47.000", "48.000", "49.000", "50.000", "51.000", "52.000", "53.000", "54.000"] ] }, { "season": "WINTER", "usage": [ ["PEAK", "55.000", "56.000", "57.000","58.000", "58.000", "59.000", "60.000", "61.000", "62.000"], ["NORMAL", "63.000", "64.000", "65.000", "66.000", "67.000", "68.000", "69.000", "70.000", "71.000"], ["OFF-PEAK", "72.000", "73.000", "74.000", "75.000", "76.000", "77.000", "78.000", "79.000","80.000"] ] }]},
result = data.vals.reduce((r,o) => {
o.usage.forEach((arr) => {
arr.slice(1).forEach((v,i) => {
r[i] = (r[i] || 0) + +v;
});
});
return r;
},[]);
console.log(result);
var data = {"vals" : [{
"season": "SUMMER",
"usage": [
["PEAK", "1.000", "2.000", "3.000", "4.000", "5.000", "6.000", "7.000", "8.000", "9.000"],
["NORMAL", "10.000", "11.000", "12.000", "13.000", "14.000", "25.000", "16.000", "17.000", "18.000"],
["OFF-PEAK", "19.000", "20.000", "21.000", "22.000", "23.000", "24.000", "25.000", "26.000", "27.000"]
]
}, {
"season": "MONSOON",
"usage": [
["PEAK", "28.000", "29.000", "30.000", "31.000", "32.000", "33.000", "34.000", "35.000", "36.000"],
["NORMAL", "37.000", "38.000", "39.000", "40.000", "41.000", "42.000", "43.000", "44.000", "45.000"],
["OFF-PEAK", "46.000", "47.000", "48.000", "49.000", "50.000", "51.000", "52.000", "53.000", "54.000"]
]
}, {
"season": "WINTER",
"usage": [
["PEAK", "55.000", "56.000", "57.000", "58.000", "58.000", "59.000", "60.000", "61.000", "62.000"],
["NORMAL", "63.000", "64.000", "65.000", "66.000", "67.000", "68.000", "69.000", "70.000", "71.000"],
["OFF-PEAK", "72.000", "73.000", "74.000", "75.000", "76.000", "77.000", "78.000", "79.000", "80.000"]
]
}]};
var result = data.vals.reduce((r,o)=>{
o.usage.forEach((a)=>{
a.slice(1).forEach((v,i)=>{
r[i] = (r[i] || 0 ) + parseFloat(v);
});
});
return r;
},[]);
console.log(result);
I have a CSV file which needs to be converted into a Javascript object / JSON file. Doesn't really matter which since I'll be be handling the data in JS anyway and either is fine.
So for instance this:
name,birthday/day,birthday/month,birthday/year,house/type,house/address/street,house/address/city,house/address/state,house/occupants
Lily Haywood,27,3,1995,Igloo,768 Pocket Walk,Honolulu,HI,7
Stan Marsh,19,10,1987,Treehouse,2001 Bonanza Street,South Park,CO,2
should become this:
[
{
"name": "Lily Haywood",
"birthday": {
"day": 27,
"month": 3,
"year": 1995
},
"house": {
"type": "Igloo",
"address": {
"street": "768 Pocket Walk",
"city": "Honolulu",
"state": "HI"
},
"occupants": 7
}
},
{
"name": "Stan Marsh",
"birthday": {
"day": 19,
"month": 10,
"year": 1987
},
"house": {
"type": "Treehouse",
"address": {
"street": "2001 Bonanza Street",
"city": "South Park",
"state": "CO"
},
"occupants": 2
}
}
]
This is what I have came up with:
function parse(csv){
function createEntry(header){
return function (record){
let keys = header.split(",");
let values = record.split(",");
if (values.length !== keys.length){
console.error("Invalid CSV file");
return;
}
for (let i=0; i<keys.length; i++){
let key = keys[i].split("/");
let value = values[i] || null;
/////
if (key.length === 1){
this[key] = value;
}
else {
let newKey = key.shift();
this[newKey] = this[newKey] || {};
//this[newKey][key[0]] = value;
if (key.length === 1){
this[newKey][key[0]] = value;
}
else {
let newKey2 = key.shift();
this[newKey][newKey2] = this[newKey][newKey2] || {};
this[newKey][newKey2][key[0]] = value;
//if (key.length === 1){}
//...
}
}
/////
}
};
}
let lines = csv.split("\n");
let Entry = createEntry(lines.shift());
let output = [];
for (let line of lines){
entry = new Entry(line);
output.push(entry);
}
return output;
}
My code works, however there is an obvious flaw to it: for each layer it goes down into (e.g. house/address/street), I have to manually write repeated if / else statements.
Is there a better way to write it? I know this involves recursion or iteration of some kind but I just can't seem to figure out how.
I've searched around SO but most questions seem to be on doing it in Python instead of JS.
As far as possible I wish to have this done in vanilla JS without any other libraries.
You can achieve the intended results by creating the Object recursively.
Look at the code below:
var csv = [
"name,birthday/day,birthday/month,birthday/year,house/type,house/address/street,house/address/city,house/address/state,house/occupants",
"Lily Haywood,27,3,1995,Igloo,768 Pocket Walk,Honolulu,HI,7",
"Stan Marsh,19,10,1987,Treehouse,2001 Bonanza Street,South Park,CO,2"
];
var attrs = csv.splice(0,1);
var result = csv.map(function(row) {
var obj = {};
var rowData = row.split(',');
attrs[0].split(',').forEach(function(val, idx) {
obj = constructObj(val, obj, rowData[idx]);
});
return obj;
})
function constructObj(str, parentObj, data) {
if(str.split('/').length === 1) {
parentObj[str] = data;
return parentObj;
}
var curKey = str.split('/')[0];
if(!parentObj[curKey])
parentObj[curKey] = {};
parentObj[curKey] = constructObj(str.split('/').slice(1).join('/'), parentObj[curKey], data);
return parentObj;
}
console.log(result);
.as-console-wrapper{max-height: 100% !important; top:0}
constructObj() function basically constructs the resultant object recursively by looking at the column name, so if the column name contains the / like in house/address/street it will create a key in the object by the name house and then recursively calls itself for the rest of the remaining keys in string i.e. address/street/. The recursion ends when no more / are left in the string and then it simply assigns the value in that key and returns the result object.
You can map over your records and create the objects on the fly :
let records = ['Lily Haywood,27,3,1995,Igloo,768 Pocket Walk,Honolulu,HI,7',
'Stan Marsh,19,10,1987,Treehouse,2001 Bonanza Street,South Park,CO,2']
let output = records.map( record => {
let arr = record.split(',')
return {
"name": arr[0],
"birthday": {
"day": parseInt(arr[1]),
"month": parseInt(arr[2]),
"year": parseInt(arr[3])
},
"house": {
"type": arr[4],
"address": {
"street": arr[5],
"city": arr[6],
"state": arr[7]
},
"occupants": parseInt(arr[8])
}
}
})
console.log(output)