JSON To Html Table With Merged Row For Each 2 Objects - javascript

Let's say, I have an Array of object:
var jsonData = [{
"Mass": "3",
"Force": "3.1",
"Acceleration": "3"
}, {
"Mass": "3",
"Force": "4.1",
"Acceleration": "3"
}, {
"Mass": "4",
"Force": "4.1",
"Acceleration": "4"
}, {
"Mass": "4",
"Force": "4.1",
"Acceleration": "4"
}, {
"Mass": "0",
"Force": "0",
"Acceleration": "0"
}, {
"Mass": "0",
"Force": "0",
"Acceleration": "0"
}];
What I want is to convert this JSON to a table like this for each of
2 objects serially where Mass and Acceleration cells are merged.

You can do this with reduce method and % operator to add element to an array on every 2nd element and then based on that new array you can build table.
var jsonData = [{"Mass":"3","Force":"3.1","Acceleration":"3"},{"Mass":"3","Force":"4.1","Acceleration":"3"},{"Mass":"4","Force":"4.1","Acceleration":"4"},{"Mass":"4","Force":"4.1","Acceleration":"4"},{"Mass":"0","Force":"0","Acceleration":"0"},{"Mass":"0","Force":"0","Acceleration":"0"}]
const result = jsonData.reduce((r, e, i, a) => {
// when index is 0, 2, 4 ... (every 2nd)
if (i % 2 == 0) {
// get also the next element 1, 3, 5
const next = a[i + 1];
// create a copy of current element and force as array
const obj = { ...e, Force: [e.Force] }
// if there is next element push its force to array
if (next) obj.Force.push(next.Force);
// push that new object to accumulator
r.push(obj)
}
return r;
}, []);
const table = $('table');
const thead = table.find('thead');
const tbody = table.find('tbody');
Object.keys(result[0]).forEach(key => {
thead.append($('<th>', {
text: key
}))
})
result.forEach(e => {
const row = $('<tr>');
row.append($('<td>', {
text: e.Mass
}));
const force = $('<td>');
e.Force.forEach(f => {
const forceRow = $("<tr>");
forceRow.append($('<td>', {
text: f
}));
force.append(forceRow);
});
row.append(force);
row.append($('<td>', {
text: e.Acceleration
}));
tbody.append(row)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1">
<thead></thead>
<tbody></tbody>
</table>

Related

filter an array to return the best percentage of each user in javascript

I have an array called data that keeps users information. I want to filter it to return the best percentage of each user for me.how can I do this.
this is my array:
let data = [ {
"userId": "1",
"percent": 97.58,
},
{
"userId": "1",
"percent": 92.01,
},
{
"userId": "2",
"percent": 91.64,
},
{
"userId": "2",
"percent": 91.64,
},
{
"userId": "3",
"percent": 91.64,
}]
I would use reduce:
let data = [
{ "userId": "1", "percent": 97.58, },
{ "userId": "1", "percent": 92.01, },
{ "userId": "2", "percent": 91.12, },
{ "userId": "2", "percent": 91.64, },
{ "userId": "3", "percent": 91.45, }
]
const bestGrades = data.reduce((acc, cur) => {
acc[cur.userId] = acc[cur.userId] || 0; // initialise the entry
acc[cur.userId] = Math.max(acc[cur.userId],cur.percent); // take the greatest
return acc;
}, {})
console.log(bestGrades)
reduce is a useful method as it allows you to accumulate new information into a new object as you iterate over the array.
const data=[{userId:"1",percent:97.58},{userId:"1",percent:92.01},{userId:"2",percent:91.64},{userId:"2",percent:91.64},{userId:"3",percent:91.64}];
const out = data.reduce((acc, c) => {
// Grab the id and percentage from the current object
const { userId: id, percent } = c;
// If the initial object that you pass in (the accumulator)
// doesn't have a property with a key that matches the id
// set a new property with the percentage value
acc[id] = acc[id] || percent;
// If the value of the percentage of the current object
// is greater than the value set on the existing property
// update it
if (percent > acc[id]) acc[id] = percent;
// Return the accumulator for the next iteration
return acc;
}, {});
console.log(out);

sort an array of objects based on previous and next id

I have an array of task objects containing previous and next task ids. I need to display an array of tasks which are sorted based on previous and next task ids. For example:
My input task array is
[
{
"taskId": "101",
"previousTaskId":"0",
"nextTaskId":"102"
},
{
"taskId": "103",
"previousTaskId":"102",
"nextTaskId":"0"
},
{
"taskId": "102",
"previousTaskId":"101",
"nextTaskId":"103"
}
]
My output task array is:
[
{
"taskId": "101",
"previousTaskId":"0",
"nextTaskId":"102"
},
{
"taskId": "102",
"previousTaskId":"101",
"nextTaskId":"103"
},
{
"taskId": "103",
"previousTaskId":"102",
"nextTaskId":"0"
}
]
Is there any way to implement it using es6 methods? I am trying to use reduce and map functionality
const sortedTasks = tasks.reduce((acc, task) => {
let {taskId, previousTaskId, nextTaskId} = task;
return {...acc, task.map(function(item){
if(item.previousTaskId === 0) //first position
//how to compare with another taskId and assign it to acc ?
})
};
}, {});
You could build a reference from each predecessor to the node and build the result from zero.
function sort(array) {
const
temp = data.reduce((t, o) => {
t[o.previousTaskId] = o;
return t;
}, {}),
result = [];
let p = '0';
while (temp[p]) {
result.push(temp[p]);
p = temp[p]?.taskId;
}
return result;
}
const
data = [{ taskId: "101", previousTaskId: "0", nextTaskId: "102" }, { taskId: "103", previousTaskId: "102", nextTaskId: "0" }, { taskId: "102", previousTaskId: "101", nextTaskId: "103" }];
console.log(sort(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }

How parse JSON with complex nesting and unnamed array?

I am trying to figure out how to parse the JSON response I receive when I make a call to a specific database (JSON response shown below) using vanilla javascript - and so far I have not had any luck. I am placing an API call to the Quickbase database and they have a standard formatting for their JSON response. The API i am calling can be found at this link: https://developer.quickbase.com/operation/runQuery.
Here is what a response from the API call looks like
{
"data": [
{
"6": {
"value": 11.0
},
"69": {
"value": "A"
},
"70": {
"value": "B"
}
},
{
"6": {
"value": 11.0
},
"69": {
"value": "C"
},
"70": {
"value": "D"
}
}
],
"fields": [
{
"id": 6,
"label": "Related Invoice",
"type": "numeric"
},
{
"id": 69,
"label": "TEST1",
"type": "text"
},
{
"id": 70,
"label": "TEST2",
"type": "text"
}
],
"metadata": {
"numFields": 3,
"numRecords": 2,
"skip": 0,
"totalRecords": 2
}
}
And this is what I want to parse it into (do NOT need to omit the JSON not shown here - I just did that for clarity)
{
"data": [
{
"Related Invoice":11.0,
"TEST1":"A",
"TEST2":"B"
},
{
"Related Invoice":11.0,
"TEST1":"C",
"TEST2":"D"
}
]
}
Below is the full javascript code i am using
let headers = {
'QB-Realm-Hostname': 'XXXXXX',
'User-Agent': 'Invoice',
'Authorization': 'XXXXXX',
'Content-Type': 'application/json'
}
let body =
{
"from": "bq2paydp2",
"select": [
6,
69,
70
],
"where": "{6.EX.11}",
"sortBy": [
{
"fieldId": 6,
"order": "ASC"
},
{
"fieldId": 69,
"order": "ASC"
}
]
}
const xmlHttp = new XMLHttpRequest();
xmlHttp.open('POST', 'https://api.quickbase.com/v1/records/query', true);
for (const key in headers) {
xmlHttp.setRequestHeader(key, headers[key]);
}
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === XMLHttpRequest.DONE) {
console.log(xmlHttp.responseText);
let line_items = JSON.parse(this.responseText, dataReviver);
console.log(line_items);
//function dataReviver (key, value) {
//if (key = 6)
// {
// var newHeaderName = 99;
// return newHeaderName;
// }
//
// return value;
//}
//document.getElementById('abc').innerHTML = line_items.data[0][6].value;
function generateTableHead(table,tableData) {
let thead = table.createTHead();
let row = thead.insertRow();
for (let key of tableData) {
let th = document.createElement("th");
let text = document.createTextNode(key);
th.appendChild(text);
row.appendChild(th);
}
};
function generateTable(table, tableData) {
for (let element of tableData) {
let row = table.insertRow();
for (key in element) {
let cell = row.insertCell();
let text = document.createTextNode(element[key]);
cell.appendChild(text);
}
}
};
let table = document.querySelector("table");
let tableData = Object.keys(line_items.data[0]);
generateTableHead(table, tableData);
generateTable(table, line_items.data);
}
};
xmlHttp.send(JSON.stringify(body));
This is what I am trying to achieve
|-----------------------------------------|
| Count | Related Invoice | TEST1 | TEST2 |
|-------|-----------------|-------|-------|
| 1 | 11.0 | A | B |
|-------|-----------------|-------|-------|
| 2 | 11.0 | C | D |
|-----------------------------------------|
I need to accomplish 3 things:
#1 Rename "6", "69 and "70" to the corresponding fields.label ( "Related Invoice", "TEST1" and "TEST2" ).
#2 Take the value of the objects nested under the objects shown above in #1 ( 11.0, "A", "B", ... ) and set them as the value of the objects shown in #1 above. This would, for example, make 6 (Related Invoice) the key and 11.0 the value.
#3 I ultimately want to display this in a table on a webpage. the html and css I can handle its the Javascript and JSON that I am not that great with.
If you need me to clarify anymore information please let me know.
To transform the data in the way you're looking, you'll need to loop over the data key in the object and create a new array based on the result of the loop.
A way to do this is with Array.prototype.map(). With this you can loop over each item in the array and return a new value.
In this map loop you are looping over each item in the data array. For each item you'll want to get the id and label from the fields array and use that array to create a new object. To create a new object within in a loop, you could use the Array.prototype.reduce() method.
So in this case you'll have a nested loop. The inner loop will loop over the fields array and uses the id to get the correct value from data array. It then returns an object with the label and the value set like you requested. The surrounding map method will then return a new array with objects. Tadaa, magic!
const response = {
"data": [{
"6": {
"value": 11.0
},
"69": {
"value": "A"
},
"70": {
"value": "B"
}
},
{
"6": {
"value": 11.0
},
"69": {
"value": "C"
},
"70": {
"value": "D"
}
}
],
"fields": [{
"id": 6,
"label": "Related Invoice",
"type": "numeric"
},
{
"id": 69,
"label": "TEST1",
"type": "text"
},
{
"id": 70,
"label": "TEST2",
"type": "text"
}
],
"metadata": {
"numFields": 3,
"numRecords": 2,
"skip": 0,
"totalRecords": 2
}
};
const transformResponseData = (response) => {
const { data, fields } = response;
// Return a new array with objects based on the values
// of the data and fields arrays.
const revivedData = data.map(entry =>
fields.reduce((object, { id, label }) => {
object[label] = entry[id].value;
return object;
}, {})
);
// Combine the original object with the new data key.
return {
...response,
data: revivedData
};
};
const createTable = ({ data, fields }) => {
const table = document.createElement('table');
const tHead = table.createTHead();
const tBody = table.createTBody();
const tHeadRow = tHead.insertRow();
// Create the counts cell manually.
const tHeadRowCountCell = document.createElement('th');
tHeadRowCountCell.textContent = 'Count';
tHeadRow.append(tHeadRowCountCell);
// Create a head for each label in the fields array.
for (const { label } of fields) {
const tHeadRowCell = document.createElement('th');
tHeadRowCell.textContent = label;
tHeadRow.append(tHeadRowCell);
}
// Output all the values of the new data array.
for (const [index, entry] of data.entries()) {
const tBodyRow = tBody.insertRow();
// Create a new array with the index and the
// values from the object.
const values = [
index + 1,
...Object.values(entry)
];
// Loop over the combined values array.
for (const [index, value] of values.entries()) {
const tBodyCell = tBodyRow.insertCell();
tBodyCell.textContent = index === 1 ?
value.toFixed(1) :
value;
}
}
return table;
};
const data = transformResponseData(response);
const table = createTable(data);
document.body.append(table);

Filter value of object in VueJS

I need to check if the value of startAt is present in an object. It should return the id of that object if it's in it.
Object:
[{
"id": "1234567",
"createTimestamp": "2020",
"name": {
"action": "",
"allDay": false,
"category": "Misc",
"startAt": "05",
"title": "foo"
},
"updateTimestamp": "2020"
}]
Below is what I have so far. The filtering works but I can't access the id to return it.
<div v-for="(hour, i) in 24" :key="i">
{{ filterByHour(hour) }}
</div>
filterByHour(id) {
if (id < 10) {
id = 0 + id
}
const result = this.events.filter(item => item.name.startAt === id.toString())
return result
}
How to return the id of the object?
I think the problem is in id = 0 + id. When id is 5 this line evaluates to 5 only not 05. Change to id = '0' + id, which will convert to string.
After the filter, use the map to extract id.
const events = [
{
id: "1234567",
createTimestamp: "2020",
name: {
action: "",
allDay: false,
category: "Misc",
startAt: "05",
title: "foo"
},
updateTimestamp: "2020"
}
];
function filterByHour(id) {
if (id < 10) {
id = "0" + id;
}
const result = events
.filter(item => item.name.startAt === String(id))
.map(x => x.id);
return result;
}
console.log(filterByHour(5));
console.log(filterByHour(11));
console.log(filterByHour());

Javascript - Get occurence of json array with ESLINT 6

I can't set up an algo that counts my occurrences while respecting ESlint's 6 standards in javascript.
My input table is :
[
{
"id": 2,
"name": "Health",
"color": "0190fe"
},
{
"id": 3,
"name": "Agriculture",
"color": "0190fe"
},
{
"id": 1,
"name": "Urban planning",
"color": "0190fe"
},
{
"id": 1,
"name": "Urban planning",
"color": "0190fe"
}
]
And i want to get :
{"Urban planning": 2, "Health": 1, ...}
But that does not work with ESLINT / REACT compilation...
This is my code :
const jsonToIterate = *'MyPreviousInputJson'*
const names = []
jsonToIterate.map(item => (names.push(item.name)))
const count = []
names.forEach(item => {
if (count[item]){
count.push({text: item, value: 1})
} else {
count.forEach(function(top){top.text === item ? top.value =+ 1 : null})
}
})
Thank you so much
Well, you want an object in the end, not an array, so count should be {}. I also wouldn't use map if you're not actually returning anything from the call. You can use reduce for this:
let counts = topicsSort.reduce((p, c, i, a) => {
if (!p.hasOwnProperty(c.name)) p[c.name] = 0;
p[c.name]++;
return p;
}, {});
I'm half exppecting someone to close this as a duplicate because all you've asked for is a frequency counter. But here's an answer anyway:
const jsonToIterate = *'MyPreviousInputJson'*;
const names = {};
jsonToIterate.map(obj => {
if(obj.name in names){
names[obj.name]++
}
else{
names[obj.name] = 1;
}
})

Categories

Resources