I need help, I got stuck on objects with multiple nested arrays. I have a json file which consists of object, that holds array of objects, and these objects have another array of objects in them. What is the best way to loop through it?
fetch("data.json").then((response) => response.json()).then((data) => {
document.getElementById("main").innerHTML += `<h1>${data.name}</h1>`;
for (i = 0; i < data.topics.length; i++) {
document.getElementById("main").innerHTML += `
<div>
<h2>${data.topics[i].title}</h2>
<ul id="programs">
<li>programs title here</li>
<li>programs title here</li>
<li>programs title here</li>
<ul>
</div>
`;
}});
json data looks like this:
{
"name": "Open Day Event",
"date": "July 7",
"topics": [
{
"title": "Engineering",
"id": 1,
"description": "some text here",
"programs": [
{
"title": "Some title",
"id": 1,
"description": "Some description",
"price": 30
},
{
"title": "Some title",
"id": 2,
"description": "Some description",
"price": 30
},
{
"title": "Some title",
"id": 3,
"description": "Some description",
"price": 30
}
]
},
{
"title": "History",
"id": 2,
"description": "some text here",
"programs": [
{
"title": "Some title",
"id": 1,
"description": "Some description",
"price": 30
},
{
"title": "Some title",
"id": 2,
"description": "Some description",
"price": 30
},
{
"title": "Some title",
"id": 3,
"description": "Some description",
"price": 30
}
]
},
{
"title": "English",
"id": 3,
"description": "some text here",
"programs": [
{
"title": "Some title",
"id": 1,
"description": "Some description",
"price": 30
},
{
"title": "Some title",
"id": 2,
"description": "Some description",
"price": 30
},
{
"title": "Some title",
"id": 3,
"description": "Some description",
"price": 30
}
]
}
]
}
You can use Array.prototype.forEach()
let html = "";
data.topics.forEach(topic => {
html += `<h2>${topic.title}</h2> <ul>`;
topic.programs.forEach(program => {
html += `<li>${program.title}</li>`
});
html += `</ul>`
})
document.getElementById('main').innerHTML = html;
You can achieve that recursively and by iterating the nested array.
Demo :
const jsonObj = {
"name": "Open Day Event",
"date": "July 7",
"topics": [{
"title": "Engineering",
"id": 1,
"description": "some text here",
"programs": [{
"title": "Some title",
"id": 1,
"description": "Some description",
"price": 30
}, {
"title": "Some title",
"id": 2,
"description": "Some description",
"price": 30
}, {
"title": "Some title",
"id": 3,
"description": "Some description",
"price": 30
}]
}, {
"title": "History",
"id": 2,
"description": "some text here",
"programs": [{
"title": "Some title",
"id": 1,
"description": "Some description",
"price": 30
}, {
"title": "Some title",
"id": 2,
"description": "Some description",
"price": 30
}, {
"title": "Some title",
"id": 3,
"description": "Some description",
"price": 30
}]
}, {
"title": "English",
"id": 3,
"description": "some text here",
"programs": [{
"title": "Some title",
"id": 1,
"description": "Some description",
"price": 30
}, {
"title": "Some title",
"id": 2,
"description": "Some description",
"price": 30
}, {
"title": "Some title",
"id": 3,
"description": "Some description",
"price": 30
}]
}]
};
function createList(parent, array) {
array.forEach(function (o) {
var li = document.createElement("li"),
ul;
li.textContent = o.title;
parent.appendChild(li);
if (o.programs) {
ul = document.createElement("ul");
li.appendChild(ul);
createList(ul, o.programs);
}
});
}
createList(document.querySelector("ul"), jsonObj.topics);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<ul></ul>
Related
I have the below array which has a sub array of categories, I would like to output the array over and over but grouping the items into another array based on their related categories
testData2: any = [{
"id": 0,
"name": "XyZ",
"category": [ {
"title": "horse"
}, {
"title": "food"
}]
}, {
"id": 2,
"name": "something 2",
"category": [{
"title": "fishing"
}, {
"title": "horse"
}, {
"title": "food"
}]
},
{
"id": 3,
"name": "something 3",
"category": [{
"title": "horse"
}]
}, {
"id": 4,
"name": "something 4",
"category": [{
"title": "food"
}, {
"title": "beer"
}]
}, {
"id": 5,
"name": "something 4",
"category": [{
"title": "fishing"
}]
}
]
So far I have this which works, but i cant help wonder if there is some new JS magic which may be more perfomant to accomplish this ?
let newArray = [];
for (let x = 0; x < this.testData2.length; x++) {
let parent = this.testData2[x];
let child = parent.category;
for (let y = 0; y < child.length; y++) {
let cat = child[y];
let format = parent
newArray.push({ group_heading: cat.title, services: [format] })
}
}
let finalOutput = newArray.reduce((acc, curr) => {
const ndx = acc.findIndex((e: any) => e.group_heading === curr.group_heading);
if(ndx > -1){
acc[ndx].services.push(...curr.services)
} else{
acc.push(curr)
}
return acc;
}, [])
which outputs this as desired
[{
"group_heading": "horse",
"services": [{
"id": 0,
"name": "XyZ",
"category": [{
"title": "horse"
}, {
"title": "food"
}]
}, {
"id": 2,
"name": "something 2",
"category": [{
"title": "fishing"
}, {
"title": "horse"
}, {
"title": "food"
}]
}, {
"id": 3,
"name": "something 3",
"category": [{
"title": "horse"
}]
}]
}, {
"group_heading": "food",
"services": [{
"id": 0,
"name": "XyZ",
"category": [{
"title": "horse"
}, {
"title": "food"
}]
}, {
"id": 2,
"name": "something 2",
"category": [{
"title": "fishing"
}, {
"title": "horse"
}, {
"title": "food"
}]
}, {
"id": 4,
"name": "something 4",
"category": [{
"title": "food"
}, {
"title": "beer"
}]
}]
}, {
"group_heading": "fishing",
"services": [{
"id": 2,
"name": "something 2",
"category": [{
"title": "fishing"
}, {
"title": "horse"
}, {
"title": "food"
}]
}, {
"id": 5,
"name": "something 4",
"category": [{
"title": "fishing"
}]
}]
}, {
"group_heading": "beer",
"services": [{
"id": 4,
"name": "something 4",
"category": [{
"title": "food"
}, {
"title": "beer"
}]
}]
}]
I would probably do something like this:
// first collect services by category
const servicesByCategory = {}
for(const service of testData2){
for(const {title} of service.category){
if(!servicesByCategory[title]){
servicesByCategory[title] = []
}
servicesByCategory[title].push(data)
}
}
// whip it into whatever form you need
return Object.entries(servicesByCategory)
.map(([group_headings, services]) => ({group_headings, services}))
I have an array of objects with duplicates:
[
{
"code": "d1",
"title": "Title 1"
},
{
"code": "d2",
"title": "Title 2"
},
{
"code": "d3",
"title": "Title 3"
},
{
"code": "d4",
"title": "Title 4"
},
{
"code": "d4",
"title": "Title 4"
},
{
"code": "d3",
"title": "Title 3"
}
]
So i want the output to be having only the once which doesn't have duplicates included like below:
[
{
"code": "d1",
"title": "Title 1"
},
{
"code": "d2",
"title": "Title 2"
}
]
Any help would be appreciated, Thanks!
Find unique's values in an array.
const ressult = YourArray.filter(
(value, index, array) => array.findIndex((v) => v.code === value.code) === index
);
Here is one way of doing it:
const products=[
{
"code": "d1",
"title": "Title 1"
},
{
"code": "d2",
"title": "Title 2"
},
{
"code": "d3",
"title": "Title 3"
},
{
"code": "d4",
"title": "Title 4"
},
{
"code": "d4",
"title": "Title 4"
},
{
"code": "d3",
"title": "Title 3"
}
];
const res=Object.entries(products.reduce((a,c)=>{
(a[c.code+"|"+c.title]??=[]).push(c);
return a;
},{})).reduce((a,[k,v])=>{
if(v.length==1) a.push(v[0]);
return a;
},[]);
console.log(res);
My approach involves two .reduce() loops:
In the first one I generate an object that collects all elements of the original array behind a compound key made up of the properties of the elements.
the object is then converted into an array again with Object.entries()
and in a second .reduce() only those elements will be collected (i. e.: their first element) into the target array that have a length of 1
let val = [
{
"code": "d1",
"title": "Title 1"
},
{
"code": "d2",
"title": "Title 2"
},
{
"code": "d3",
"title": "Title 3"
},
{
"code": "d4",
"title": "Title 4"
},
{
"code": "d4",
"title": "Title 4"
},
{
"code": "d3",
"title": "Title 3"
}
];
let distinctVal = getDistincts(val);
function getDistincts(val){
let obj={};
for (let i = 0; i < val.length; i++) {
obj[`${val[i]["code"]}`]=val[i]["title"];
}
return obj;
}
console.log(distinctVal);
I am unable to create this logic, trying for hours. I just need to add index and subIndex properties with increments and on behave of different eventTicketId.
For a single ticket, for example eventTicketId:461. I have to have 2 fields like first ticket and its first value and then first ticket and its second value. Same goes for other tickets like for eventTicketId:463 it will go like first ticket and its first value, first ticket and its second value, second ticket and its first value and at last second ticket and its second value.
Orignal Array:
let ticketArray = [
{
"eventTicketId": "461",
"title": "Name 1",
"value": "salman",
"type": 'name'
},
{
"eventTicketId": "461",
"title": "CNIC 1",
"value": "31221321",
"type": 'cnic'
},
{
"eventTicketId": "462",
"title": "Name 1",
"value": "asdfasdf",
"type": 'name'
},
{
"eventTicketId": "462",
"title": "CNIC 1",
"value": "31221321",
"type": 'cnic'
},
{
"eventTicketId": "463",
"title": "Name 1",
"value": "Adsadsa",
"type": 'name'
},
{
"eventTicketId": "463",
"title": "CNIC 1",
"value": "321312312",
"type": 'cnic'
},
{
"eventTicketId": "463",
"title": "Name 2",
"value": "Adsadsa",
"type": 'name'
},
{
"eventTicketId": "463",
"title": "CNIC 2",
"value": "133213",
"type": 'cnic'
}];
Required Array:
let ticketArray = [
{
"eventTicketId": "461",
"title": "Name 1",
"value": "salman",
"type": 'name',
"index": "1",
"subIndex": "1"
}, {
"eventTicketId": "461",
"title": "CNIC 1",
"value": "31221321",
"type": 'cnic',
"index": "1",
"subIndex": "2"
},
{
"eventTicketId": "462",
"title": "Name 1",
"value": "asdfasdf",
"type": 'name',
"index": "1",
"subIndex": "1"
},
{
"eventTicketId": "462",
"title": "CNIC 1",
"value": "31221321",
"type": 'cnic',
"index": "1",
"subIndex": "2"
},
{
"eventTicketId": "463",
"title": "Name 2",
"value": "Adsadsa",
"type": 'name',
"index": "1",
"subIndex": "1"
},
{
"eventTicketId": "463",
"title": "CNIC 2",
"value": "133213",
"type": 'cnic',
"index": "1",
"subIndex": "2"
},
{
"eventTicketId": "463",
"title": "Name 1",
"value": "Adsadsa",
"type": 'name',
"index": "2",
"subIndex": "1"
},
{
"eventTicketId": "463",
"title": "CNIC 1",
"value": "321312312",
"type": 'cnic',
"index": "2",
"subIndex": "2"
},];
I made a snippet with what I think would be a possible answer to your problem.
let ticketArray = [
{
"eventTicketId": "461",
"title": "Name 1",
"value": "salman",
"type": 'name'
},
{
"eventTicketId": "461",
"title": "CNIC 1",
"value": "31221321",
"type": 'cnic'
},
{
"eventTicketId": "462",
"title": "Name 1",
"value": "asdfasdf",
"type": 'name'
},
{
"eventTicketId": "462",
"title": "CNIC 1",
"value": "31221321",
"type": 'cnic'
},
{
"eventTicketId": "463",
"title": "Name 1",
"value": "Adsadsa",
"type": 'name'
},
{
"eventTicketId": "463",
"title": "CNIC 1",
"value": "321312312",
"type": 'cnic'
},
{
"eventTicketId": "463",
"title": "Name 2",
"value": "Adsadsa",
"type": 'name'
},
{
"eventTicketId": "463",
"title": "CNIC 2",
"value": "133213",
"type": 'cnic'
}];
const tickets = {};
const result = ticketArray.map(ticket => {
let subIndex = 1
if (tickets[ticket.eventTicketId]) {
tickets[ticket.eventTicketId] += 1
} else {
tickets[ticket.eventTicketId] = 1
}
let index = Math.ceil(tickets[ticket.eventTicketId] / 2);
subIndex = tickets[ticket.eventTicketId] % 2 == 0 ? 2 : 1
return {...ticket, index, subIndex}
})
console.log(result)
I have data coming from service in the below json array.
"data": [
{
"id": 1,
"roneName": "1",
"description": "Test1",
"companyId": 101,
"permissionList": [
{
"id": 1,
"name": "permission 1",
"description": "",
},
{
"id": 2,
"name": "permission 2",
"description": ""
},
{
"id": 3,
"name": "permission 3",
"description": ""
},
{
"id": 4,
"name": "permission 4",
"description": ""
}
]
},
{
"id": 2,
"roneName": "Test2",
"description": "Test2",
"companyId": 101,
"permissionList": [
{
"id": 1,
"name": "permission 1",
"description": ""
}
]
},
{
"id": 3,
"name": "Test 3",
"description": "Test 3",
"companyId": 101,
"permissionList": [
{
"id": 1,
"name": "Test1",
"description": ""
},
{
"id": 2,
"name": "test 2",
"description": ""
},
{
"id": 3,
"name": "test 3",
"description": "test 3"
}
]
}
]
i want to display data in the angular mat-table in below format
**Permission Name** **roleName1** **roleName2** **roleName3**
permission 1 checkbox checked checkbox checked checkbox checked
permission 2 checkbox unchecked checkbox checked checkbox unchecked
permission 3 checkbox checked checkbox unchecked checkbox checked
I would like to filter away the objects in my array of objects that has null or "" values.
let data = [{
"name": "Product 2",
"link": "/stock/product2",
"category": "234",
"description": ""
}, {
"name": "Product 1",
"link": "/stock/product1",
"category": "1231",
"description": ""
}, {
"name": "",
"link": null,
"ticker": "",
"description": ""
}]
data = data.filter(cv => (cv.name === "" && cv.link === null));
console.log(JSON.stringify(data))
As you can see above I currently get the false object back. I would like to get back:
{
"name": "Product 2",
"link": "/stock/product2",
"category": "234",
"description": ""
}, {
"name": "Product 1",
"link": "/stock/product1",
"category": "1231",
"description": ""
}
Any suggestions what I am doing wrong?
Because filter doesn't work as you think, it keeps elements that meet the condition, so invert your condition and it should work as expected:
let data = [{
"name": "Product 2",
"link": "/stock/product2",
"category": "234",
"description": ""
}, {
"name": "Product 1",
"link": "/stock/product1",
"category": "1231",
"description": ""
}, {
"name": "",
"link": null,
"ticker": "",
"description": ""
}]
data = data.filter(cv => !(cv.name === "" || cv.link === null));
console.log(JSON.stringify(data))
This will filter out items which have at least one field with null or "" value.
let data = [{
"name": "Product 2",
"link": "/stock/product2",
"category": "234",
"description": ""
}, {
"name": "Product 1",
"link": "/stock/product1",
"category": "1231",
"description": ""
}, {
"name": "",
"link": null,
"ticker": "",
"description": ""
}]
data = data.filter(cv => Object.values(cv).some(v => v == '' || v == null));
console.log(JSON.stringify(data))
The best solution for this is
let data = [{
"name": "Product 2",
"link": "/stock/product2",
"category": "234",
"description": ""
},
{
"name": "Product 1",
"link": "/stock/product1",
"category": "1231",
"description": ""
}, {
"name": "",
"link": null,
"ticker": "",
"description": ""
}
]
data = data.filter(cv => (cv.name && cv.link));
console.log(data);
You could get the values of the objects and check if some value is truty, then keep this object, otherwise filter it out.
let data = [{ name: "Product 2", link: "/stock/product2", category: "234", description: "" }, { name: "Product 1", link: "/stock/product1", category: "1231", description: "" }, { name: "", link: null, ticker: "", description: "" }]
data = data.filter(o => Object.values(o).some(Boolean));
console.log(data);