Avoid Iterating Outer Loop - javascript

I've a scenario where I've to iterate two list or arrays to get required values. So I am doing something like this:
var html = "";
$.each(list, function (i, set1) { //set1 is a list or array
$.each(set1.Tabs, function (i, set2) { //set1.Tabs is another one
html += "<li><a href='#" + set2.TabName + "'>" + set2.Details + "</a> <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>";
})
})
The above works fine, it returns me the required data. But the problem is, say the outer loop has 10 values and the inner loop has four values. So the inner loop gets iterated ten times with the four values. This is natural and it should do. I was trying to get distinct values using the following (For the outer loop specifically):
list = list.filter((x, i, a) => a.indexOf(x) === i);
Though the above should work, my expected output is as follows:
Input: [1, 2, 3, 3, 4, 5, 6, 6]
Output: [1, 2, 3, 4, 5, 6]
N.B: My concern is with the inner loop, not with the outer one. But to iterate the inner loop, I've to go through the outer loop. Is there any way I can get the inner loop work directly?
Update 1: Sample Code
$(document).ready(function() {
var html = "";
var data = [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" }
]
},
{
"id": "0002",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" }
]
}
]
$.each(data, function(i, set1) { //set1 is a list or array
$.each(set1.topping, function(i, set2) { //set1.Tabs is another one
html += "<li><a href='#" + set2.id + "'>" + set2.type + "</a> <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>";
})
})
$('#add').append(html);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="add"></div>

You can create unique toppings based on the id and then render the list using unique toppings. To create unique toppings, you can use flatMap() Object.values() and array#reduce.
$(document).ready(function() {
var html = "";
var data = [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5007",
"type": "Powdered Sugar"
}
]
},
{
"id": "0002",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"topping": [{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5007",
"type": "Powdered Sugar"
}
]
}
]
const uniqueToppings = Object.values(data
.flatMap(o => o.topping)
.reduce((r, {id, type}) => {
r[id] = r[id] || {id, type};
return r;
},{}));;
$.each(uniqueToppings, function(i, set) {
html += "<li><a href='#" + set.id + "'>" + set.type + "</a> <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>";
});
$('#add').append(html);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="add"></div>

Related

How to dynamically create and iterate Json Object inside a Json Array using Postman - Javascript

I have a payload like mentioned below :
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [
{
"id": "1001",
"type": "Regular"
},
{
"id": "1002",
"type": "Chocolate"
},
{
"id": "1003",
"type": "Blueberry"
},
{
"id": "1004",
"type": "Devil’sFood"
}
]
},
"topping": [
{
"id": "5001",
"type": "None"
},
{
"id": "5002",
"type": "Glazed"
},
{
"id": "5005",
"type": "Sugar"
},
{
"id": "5007",
"type": "PowderedSugar"
},
{
"id": "5006",
"type": "ChocolatewithSprinkles"
},
{
"id": "5003",
"type": "Chocolate"
},
{
"id": "5004",
"type": "Maple"
}
]
}
**I want to increment the json objects dynamically(it can be a duplicate as well) which is inside the array topping based on the array size. For example if mention the array size as topping[10] it is suppose to create a payload of 10 objects and push those 10 objects of similar type inside the array topping ** Is it possible to dynamically create json objects and post the request in postman??
Kind note : The size of the array should be parameterized. Please let me know.
Please find the image highlighted in green. I want to dynamically increase the payload(topping array size based on the index using postman
You could do this:
Tab Pre-request
let req = {
"id": "0001",
"type": "donut",
"topping": []
};
let numberOfTopping = 5;
for (let i = 0; i < numberOfTopping; i++) {
let toppingItem = {
"id": `${_.random(5001, 5010)}`,
"type": `${_.sample(["Glazed", "Sugar", "None"])}`
};
req.topping[i] = toppingItem;
}
pm.variables.set("req", JSON.stringify(req));
Tab body
Result
{
"id": "0001",
"type": "donut",
"topping": [
{
"id": "5006",
"type": "Glazed"
},
{
"id": "5001",
"type": "Sugar"
},
{
"id": "5006",
"type": "Glazed"
},
{
"id": "5006",
"type": "None"
},
{
"id": "5008",
"type": "Sugar"
}
]
}

Retrieving Nested JSON Array with AJAX and Outputting to an HTML List

The idea is to take a JSON array, loop through each of the entries for planets and output them to an unordered list, with one entry per li. All works well in this instance.
I have successfully written a method to output nested JSON when the JavaScript file contains the JSON array and the code below it, but I am having serious trouble identifying a method to retrieve the same data from an external .json file, using AJAX.
Here is the working local version.
<ul id="object-list"></ul>
$(document).ready( function() {
var sol_sys = [];
sol_sys = {
"stars": [
{ "name": "Sun", "object": "Star", "url": "stars/sun" }
],
"planets": [
{ "name": "Mercury", "object": "Planet", "parent": "Sun", "url": "planets/mercury" },
{ "name": "Venus", "object": "Planet", "parent": "Sun", "url": "planets/venus" },
{ "name": "Earth", "object": "Planet", "parent": "Sun", "url": "planets/earth" },
{ "name": "Mars", "object": "Planet", "parent": "Sun", "url": "planets/mars" },
{ "name": "Ceres", "object": "Dwarf Planet", "parent": "Sun", "url": "planets/ceres" },
{ "name": "Jupiter", "object": "Planet", "parent": "Sun", "url": "planets/jupiter" },
{ "name": "Saturn", "object": "Planet", "parent": "Sun", "url": "planets/saturn" },
{ "name": "Uranus", "object": "Planet", "parent": "Sun", "url": "planets/uranus" },
{ "name": "Neptune", "object": "Planet", "parent": "Sun", "url": "planets/neptune" },
{ "name": "Pluto", "object": "Dwarf Planet", "parent": "Sun", "url": "planets/pluto" },
{ "name": "Eris", "object": "Dwarf Planet", "parent": "Sun", "url": "planets/eris" }
],
"moons": [
{ "name": "Luna", "object": "Moon", "parent": "Earth", "url": "moons/luna" },
{ "name": "Callisto", "object": "Moon", "parent": "Jupiter", "url": "moons/callisto" },
{ "name": "Ganymede", "object": "Moon", "parent": "Jupiter", "url": "moons/ganymede" },
{ "name": "Io", "object": "Moon", "parent": "Jupiter", "url": "moons/io" },
{ "name": "Europa", "object": "Moon", "parent": "Jupiter", "url": "moons/europa" },
{ "name": "Enceladus", "object": "Moon", "parent": "Saturn", "url": "moons/enceladus" },
{ "name": "Titan", "object": "Moon", "parent": "Saturn", "url": "moons/titan" },
{ "name": "Miranda", "object": "Moon", "parent": "Uranus", "url": "moons/miranda" },
{ "name": "Triton", "object": "Moon", "parent": "Neptune", "url": "moons/triton" },
{ "name": "Charon", "object": "Moon", "parent": "Pluto", "url": "moons/charon" }
]
}
var x = [];
$.each(sol_sys.planets, function(index) {
x += '<li>' + sol_sys.planets[index].name + '</li>';
});
$('#object-list').append(x);
});
However, I have spent the past two days trying to figure out the method to achieve this, with the JSON kept separate in a separate .json file.
Here is an example of one method I have tried:
$(document).ready( function() {
var sol_sys = $.getJSON('assets/data.json');
var x = [];
$.each(sol_sys.planets, function(index) {
x += '<li>' + sol_sys.planets[index].name + '</li>';
});
$('#object-list').append(x);
});
This code successfully fetches the data as can be seen in the console, but it also spits out this error message:
Uncaught TypeError: Cannot read property 'length' of undefined
I am thinking that there is something obvious that I have completely missed. I have also tried the method demonstrated here, with exactly the same outcome.
Can anybody point me in the right direction?
Thanks!
$.getJSON is an async call - so you need to use the callback function to access the returned data:
$.getJSON('assets/data.json', function(sol_sys) {
var x = [];
$.each(sol_sys.planets, function(index) {
x += '<li>' + sol_sys.planets[index].name + '</li>';
});
$('#object-list').append(x);
});
Hi you can do it this way:
your ajax:
function getList() {
return $.ajax({
type: "GET",
url: "YourUrl"
})
}
call it like this:
getList().done(function(response){
var data=JSON.parse(response);
if (data != null) {
jQuery.each(data, function(index, value){
//use an id in your ul in order to append some items
$("#yourUl id").append('<li><a href=' + value.url+ '>' + value.name+ '</a></li>');
});
}
})
Or
$.getJSON( 'assets/data.json').done(function(response) {
var data=JSON.parse(response);
if (data != null) {
jQuery.each(data, function(index, value){
//use an id in your ul in order to append some items
$("#yourUl id").append('<li><a href=' + value.url+ '>' + value.name+ '</a></li>');
});
}
})
Edit: append the elements like this:
$.getJSON( 'data.json').done(function(response) {
jQuery.each(response, function(index, value){
$("#planetList").append('<li>'+index+'</li>');
jQuery.each(value, function(index2, value2){
$("#planetList").append('<ul><li><a href=' +value2.url+ '>' +value2.name+ '</a></li>')
console.log(value2);
})
$("#planetList").append('<ul>');
})
})
Hope it helps

Creating Array with String and Integers from JSON

Currently I've got the following JSON feed:
var data = {
"feeds": {
"regions": [{
"name": "Lichtenberg",
"id": "01408.b",
"suburbs": [{
"name": "Fennpfuhl",
"views": 76400
},
{
"name": "Lichtenberg",
"views": 87895
},
{
"name": "Rummelsberg",
"views": 10239
}
]
},
{
"name": "Mitte",
"id": "03442.f",
"suburbs": [{
"name": "Tiergarten",
"views": 82695
},
{
"name": "Mitte",
"views": 67234
},
{
"name": "Hansaviertel",
"views": 10848
},
{
"name": "Moabit",
"views": 67500
}
]
},
{
"name": "Friedrichshain-Kreuzberg",
"id": "01991.o",
"suburbs": [{
"name": "Friedrichshain",
"views": "98494"
},
{
"name": "Kreuzberg",
"views": "27800"
}
]
},
{
"name": "Templehof-Schöneberg",
"id": "01778.k",
"suburbs": [{
"name": "Friedenau",
"views": 76595
},
{
"name": "Schöneberg",
"views": 20731
},
{
"name": "Templehof",
"views": 58000
},
{
"name": "Mariendorf",
"views": 32300
}
]
},
{
"name": "Pankow",
"id": "02761.q",
"suburbs": [{
"name": "Wießensee",
"views": 81294
},
{
"name": "Prenzlauer Berg",
"views": 76470
},
{
"name": "Pankow",
"views": 90210
}
]
}
],
}
};
Effectively I want to do two things:
Loop through the Regions to get the 4 names
Loop through all the views in each region, sum them up, and return them as values under the 4 names.
Here's a sample of the output that I just quickly typed up:
var viewsPerRegion =
[{
label: "Litchtenberg",
total: 174534
}, {
label: "Mitte",
total: 228277
}, {
label: "Friedrichshain-Kreuzberg",
total: 126294
}, {
label: "Templehof-Schöneberg",
total: 187626
}];
etc...
I do want to note that data.feeds.region[2].suburbs.views is stored as a string, so that's something I'll need to change into an integer first.
Anyway the solution I have so far (which doesn't really work) is as follows:
var viewsPerRegion, i, j, x;
for (i in data.feeds.regions) {
x += data.feeds.regions[i].name;
for (j in data.feeds.regions[i].suburbs.views){
x += data.feeds.regions[i].suburbs.views[j];
}
}
viewsPerRegion = x;
Any help is certainly appreciated - bit of a newbie in JSON and javascript.
You can map the regions array, extracting the name from each, and get the total by using reduce to add up each of the views:
const data={"feeds":{"regions":[{"name":"Lichtenberg","id":"01408.b","suburbs":[{"name":"Fennpfuhl","views":76400},{"name":"Lichtenberg","views":87895},{"name":"Rummelsberg","views":10239}]},{"name":"Mitte","id":"03442.f","suburbs":[{"name":"Tiergarten","views":82695},{"name":"Mitte","views":67234},{"name":"Hansaviertel","views":10848},{"name":"Moabit","views":67500}]},{"name":"Friedrichshain-Kreuzberg","id":"01991.o","suburbs":[{"name":"Friedrichshain","views":"98494"},{"name":"Kreuzberg","views":"27800"}]},{"name":"Templehof-Schöneberg","id":"01778.k","suburbs":[{"name":"Friedenau","views":76595},{"name":"Schöneberg","views":20731},{"name":"Templehof","views":58000},{"name":"Mariendorf","views":32300}]},{"name":"Pankow","id":"02761.q","suburbs":[{"name":"Wießensee","views":81294},{"name":"Prenzlauer Berg","views":76470},{"name":"Pankow","views":90210}]}],}}
const viewsPerRegion = data.feeds.regions.map(({ name, suburbs }) => ({
label: name,
total: suburbs.reduce((a, { views }) => a + Number(views), 0)
}));
console.log(viewsPerRegion);

Javascript to manipulate array of objects and create two set of arrays for data and link [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have an object array like the following.
[
{
"name": "car",
"value": "",
"children": [
{
"name": "v8_engine",
"value": "",
"children": [
{
"name": "cylinder-arrangement",
"value": "",
"children": [
{
"name": "type",
"value": "string",
"children": []
},
{
"name": "max-elements",
"value": "8",
"children": []
}
]
}
]
},
{
"name": "other-parts",
"value": "",
"children": [
{
"name": "per-cylinder-parts",
"value": "",
"children": [
{
"name": "piston-diameter",
"value": "",
"children": [
{
"name": "type",
"value": "uint32",
"children": []
},
{
"name": "range",
"value": "2000... 9000",
"children": []
}
]
},
{
"name": "valves",
"value": "",
"children": [
{
"name": "number",
"value": "",
"children": []
},
{
"name": "position",
"value": "",
"children": []
}
]
}
]
}
]
}
]
}
]
I want to parse through each elements and their respective childrens and manipulate it to create two set of arrays
Node data array that contains:key which is index of that element and values as shown
nodeDataArray.push({ key:i,Data: a.yang_type + " " + a.name}) or nodeDataArray.push({ key:i,Data: a.name + " " + a.value})
Link Data array that contains the link (parent child relation ship)
linkDataArray.push({ from: i, to: j });
where i is the index of parent and j is index of child
I have the following function that parses through the elements and pushes them fine in to node data array with index.
vm.tree.forEach(loop);// here vm.tree is the json data, passed dynamically
var i=0;
function loop(a) {
if(a.yang_type!='' && a.name!=''){
nodeDataArray.push({ key:i,Data: a.yang_type + " " + a.name, group: -1 });
//console.log("Data:",a.yang_type);
linkDataArray.push({ from: i, to: i+1 });
}
if(a.name!='' && a.value!=''){
nodeDataArray.push({ key:i,Data: a.name + " " + a.value, group: -1 });
linkDataArray.push({ from: 0, to: i+1 });
}
i=i+1;
// process you data
//if(Array.isArray(a.children)){j++;}
if(Array.isArray(a.children)){
//var g=0;
a.children.forEach(loop);
}
}
Below wordings is based on the sample JSON to make it more clear on what is my expected output should be
parse through the JSON and list out all the elements in the JSON object as shown below
car
v8_engine
cylinder-arrangement
type string
max-elements 8
other_parts
per-cylinder-parts
piston-diameter
type UINT32
range 2000...3000
valves
number
position
Then list of relationship based on parent and child index. Where car is the 0th element,v8_engine is the 2nd and so on … until the last one which is position being 12th
So we have total of 13 elements from the above example. Now I need to list their relation ship too. Like
0th element is parent of 1 and 5.
1st element is parent of 2
2nd element is parent of 3 and 4
and so on
To generate the parent list, you could use a closure with a from variable, which holds the node number from where it has been called.
BTW, your list above is not correct for 5th element is parent of 6 and 10.
function loop(from) {
return function (a) {
var f = i;
if (from !== undefined) {
linkDataArray.push({ from: from, to: i });
}
i++;
if (Array.isArray(a.children)) {
a.children.forEach(loop(f));
}
};
}
var data = [{ "name": "car", "value": "", "children": [{ "name": "v8_engine", "value": "", "children": [{ "name": "cylinder-arrangement", "value": "", "children": [{ "name": "type", "value": "string", "children": [] }, { "name": "max-elements", "value": "8", "children": [] }] }] }, { "name": "other-parts", "value": "", "children": [{ "name": "per-cylinder-parts", "value": "", "children": [{ "name": "piston-diameter", "value": "", "children": [{ "name": "type", "value": "uint32", "children": [] }, { "name": "range", "value": "2000... 9000", "children": [] }] }, { "name": "valves", "value": "", "children": [{ "name": "number", "value": "", "children": [] }, { "name": "position", "value": "", "children": [] }] }] }] }] }],
i = 0,
linkDataArray = [];
data.forEach(loop());
console.log(linkDataArray);
var i=0;
var nodeDataArray = [];
var linkDataArray = [];
function loop(from) {
return function (a) {
var f = i;
if(a.yang_type!='' && a.name!=''){
nodeDataArray.push({ key:i,Data: a.yang_type + " " + a.name, group: -1 });
//c=c+a.name;
//console.log("c:",c);
//console.log("Data:",a.yang_type);
//linkDataArray.push({ from: i, to: i+1 });
}
if(a.name!='' && a.value!=''){
nodeDataArray.push({ key:i,Data: a.name + " " + a.value, group: -1 });
//c=c+a.name+a.value;
console.log("c:",c);
//linkDataArray.push({ from: 0, to: i+1 });
}
if (from !== undefined) {
linkDataArray.push({ from: from, to: i });
}
i++;
if (Array.isArray(a.children)) {
a.children.forEach(loop(f));
}
//console.log("c:",c);
};
}
var data = [{ "name": "car", "value": "", "children": [{ "name": "v8_engine", "value": "", "children": [{ "name": "cylinder-arrangement", "value": "", "children": [{ "name": "type", "value": "string", "children": [] }, { "name": "max-elements", "value": "8", "children": [] }] }] }, { "name": "other-parts", "value": "", "children": [{ "name": "per-cylinder-parts", "value": "", "children": [{ "name": "piston-diameter", "value": "", "children": [{ "name": "type", "value": "uint32", "children": [] }, { "name": "range", "value": "2000... 9000", "children": [] }] }, { "name": "valves", "value": "", "children": [{ "name": "number", "value": "", "children": [] }, { "name": "position", "value": "", "children": [] }] }] }] }] }]
data.forEach(loop());

jQuery JSON append ul according to the number of array sets

I want jQuery to make new ul for each set of products.
Inside of each ul, all items of each set will be appended.
The result was unexpected; there should be only 2 ul, but
11 ul were appended.
My jQuery
$.getJSON('/products.json', function (result) {
var booksobj = result.ebooks.basic;
/* EBOOKS*/
$.each(booksobj.set, function(i, item) {
$('#ebook').append('<ul>'); // Append new list sets
$('#ebook ul').append('<li>' + item.title + '</li>');
});
});
products.json
{
"ebooks": {
"basic": {
"set": [
{
"title": "PDF Sample",
"product_id": 1,
"type": "ebook"
},
{
"title": "PDF Sample",
"product_id": 2,
"type": "ebook"
}, // ...
],
"set": [
{
"title": "PDF Sample",
"product_id": 1,
"type": "ebook"
},
{
"title": "PDF Sample",
"product_id": 2,
"type": "ebook"
}, // ...
]
}
}
}
Thanks in advance.
You're looping over set and for each item inside a set, you're creating a new ul element. You need to have multiple loops where you create an ul and afterwards add all the lis for the section. I changed your data structure, you don't need the set properties (and they're overriding each other as property names are unique). basic is now an array which consists of arrays which represent a set.
var data = {
"ebooks": {
"basic": [
[
{
"title": "PDF Sample 1",
"product_id": 1,
"type": "ebook"
},
{
"title": "PDF Sample 2",
"product_id": 2,
"type": "ebook"
},
],
[
{
"title": "PDF Sample 3",
"product_id": 1,
"type": "ebook"
},
{
"title": "PDF Sample 4",
"product_id": 2,
"type": "ebook"
},
]
]
}
}
data.ebooks.basic.forEach(function(set) {
var $list = $('<ul></ul>');
set.forEach(function(pdf) {
$list.append('<li>' + pdf.title + '</li>')
});
$('#ebook').append($list);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ebook"></div>
It looks like the problem stems from the selectors in this snippet:
$('#ebook').append('<ul>'); // Append new list sets
$('#ebook ul').append('<li>' + item.title + '</li>');
The selector "$('#ebook ul')" won't select the newly added ul in the iteration, instead it'll append to the first match (so the first ul added to the #ebook div). Instead, try chaining your calls like so:
/* EBOOKS*/
$.each(booksobj.set, function(i, item) {
$('#ebook').append('<ul>').append('<li>' + item.title + '</li>');
});
Working example with JSON data in a variable: http://codepen.io/JasonGraham/pen/WxbvRo
Your problem is use $('#ebook ul'), another question, why you use the key "set" two times? No make sense,
var data = {
"ebooks": {
"basic": [
[
{
"title": "PDF Sample 1",
"product_id": 1,
"type": "ebook"
},
{
"title": "PDF Sample 2",
"product_id": 2,
"type": "ebook"
},
],
[
{
"title": "PDF Sample 3",
"product_id": 1,
"type": "ebook"
},
{
"title": "PDF Sample 4",
"product_id": 2,
"type": "ebook"
},
]
]
}
}
$.each(data.ebooks.basic, function(i, item) {
$('#ebook').append('<ul>'); // Append new list sets
$.each(item, function(i, item2) {
$('#ebook ul:last').append('<li>' + item2.title + '</li>');
});
});
see the fiddle

Categories

Resources