I have Json data like below;
let data = [
{
"name": "John Doe",
"position": "Accountant",
"social": ["facebook", "instagram", "youtube", "pinterest"]
},
{
"name": "Michael Schumaher",
"position": "F1 Pilot",
"social": ["facebook", "instagram", "youtube", "pinterest"]
}
];
I need to loop iterate nodes and child arrays called social.
let html = '';
let i;
for ( i = 0; i < data.length; i++) {
let socArr = data[i].social;
socArr.forEach ( function ( item ) {
console.log( item + '/');
});
};
I need to display 'name position social' in the same div, but forEach loop gives me all array data in the json document.
Related to your question, I would assume that you only need two div elements. So for that scenario, I would create two statics div into your html body then feeding them with that loop. See the example below:
let data = [
{
"name": "John Doe",
"position": "Accountant",
"social": ["facebook", "instagram", "youtube", "pinterest"]
},
{
"name": "Michael Schumaher",
"position": "F1 Pilot",
"social": ["facebook", "instagram", "youtube", "pinterest"]
}
];
for (let i = 0; i < data.length; i++) {
document.getElementById('myDiv' + (i + 1)).innerHTML = data[i].name + '<br/>' + data[i].position + '<br/>';
let socArr = data[i].social;
socArr.forEach ( function ( item ) {
document.getElementById('myDiv' + (i + 1)).innerHTML += item + '<br/>';
});
document.getElementById('myDiv' + (i + 1)).innerHTML += '<br/>';
}
<div id="myDiv1"></div>
<div id="myDiv2"></div>
I cannot replicate the behavior you state. You should be able to iterate over each record (element of the array) and then iterate over its values:
let data = getData();
let body = document.querySelector('body')
let fragment = document.createDocumentFragment() // used for performance
let text = (str) => document.createTextNode(str) // used to reduce/simplify code
let br = () => document.createElement('br') // used to reduce/simplify code
data.forEach(rcd => {
// create new div for each record
let div = document.createElement('div')
// iterate over record values
for (let value of Object.values(rcd)) {
div.appendChild(text(value))
div.appendChild(br())
}
// add to fragment
fragment.appendChild(div)
});
// add to DOM
body.appendChild(fragment);
// Data structure is placed in function so logic SO is seen first
function getData() {
return [{
"name": "John Doe",
"position": "Accountant",
"social": ["facebook", "instagram", "youtube", "pinterest"]
},
{
"name": "Michael Schumaher",
"position": "F1 Pilot",
"social": ["facebook", "instagram", "youtube", "pinterest"]
}
]
}
div {
border: 1px solid;
padding: .5rem;
margin: 1em
}
Related
So I have the following array of objects:
var data = [
{
"title": "scooter",
"materials": ["wood", "metal", "glass"]
},
{
"title": "baseball bat",
"materials": ["wood", "metal"]
},
{
"title": "coffee table",
"materials": ["wood"]
}
];
Trying to get from a function the following:
From the materials array what has more than, or equal to, 2 materials and what are the items.
I've tried the following:
function testing() {
let container = [];
let items = [];
for (let i = 0; i < data.length; i++) {
container.push(data[i].materials);
for (let j = 0; j < container.length; j++) {
if (container[i][j] >= 2) {
items.push(data[i].title);
}
}
}
return(items);
}
console.log(testing());
I'm not able to get the nested array to check for length and return the title let alone the full list.
An example of what I want to see based on the criteria:
Scooter: "wood", "metal", "glass"
Baseball bat: "wood", metal"
What am I doing wrong with the code?
You can just test the material length through one loop !
let items = [];
for(let i=0 ; i<data.length; i++){
if(data[i].materials.length >= 2){
items.push(data[i].title);
}
}
You can use filter:
var data = [{"title": "scooter", "materials":["wood","metal","glass"]}, {"title": "baseball bat", "materials":["wood","metal"]}, {"title": "coffee table", "materials":["wood"]}];
console.log(
data.filter(obj => obj.materials.length >= 2)
)
Or to convert the result to key value based:
var data = [{"title": "scooter", "materials":["wood","metal","glass"]}, {"title": "baseball bat", "materials":["wood","metal"]}, {"title": "coffee table", "materials":["wood"]}];
console.log(
data.filter(obj => obj.materials.length >= 2).map(obj => ({[obj.title]: obj.materials}))
)
You can use a map function and a filter function to do this:
let result = data.map(elem => ({count: elem.materials.length, materials: elem.materials, title: elem.title })).filter(elem => elem.count >= 2);
This way you get an array containing objects in the form { count: 2, materials: ["wood", "metal"], title: "baseball bat" }
I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')
I want to get job titles and its related data such as areas and subareas. My JSON is here
{ "data":[{"IT_JOBS":{ "areas": [ "SE", "QA","PM"],"subareas":["Associate","Trainee","Developer"] },..}] }
If you want to have an array of objects, you'll need to modify your data.
{
"data":[
{
"name": "IT_JOBS",
"areas":[
"SE",
"QA",
"PM"
],
"subareas":[
"Associate",
"Trainee",
"Developer"
]
},
{
"name": "IT",
"areas":[
"SEs",
"QsA",
"PMs"
],
"subareas":[
"Assocsasdiate",
"Traineeasd",
"Developeasdasdr"
]
}
]
}
Here is a sample Jsfiddle.
for (var key in response.data) {
var obj = response.data[key];
console.log("Values for ITEM: " + key)
console.log("Name: " + obj.name);
console.log("Areas: " + obj.areas);
console.log("Subareas: " + obj.subareas);
}
If you have a single object, you can do something like this Jsfiddle.
for (let i = 0; i < response.data.length; i++) {
console.log("Values for IT_JOBS");
console.log("Areas: " + response.data[i].IT_JOBS.areas);
console.log("Subareas: " + response.data[i].IT_JOBS.subareas);
}
I am trying to parse and show JSON data (product catalog) using XMLHttpRequest method. I am able to display the brands and their names, but not able to showcase list of products progmatically.
Here is the sample JSON request:
{
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
}
Right now I am using following code to show data in tabluar form:
function loadJSON() {
var data_file = "http://localhost/AJAX/productcatalog.json";
var http_request = new XMLHttpRequest();
http_request.onreadystatechange = function () {
if ((http_request.readyState == 4) && (http_request.status == 200)) {
// Javascript function JSON.parse to parse JSON data
var jsonObj = JSON.parse(http_request.responseText);
data = '<table border="2"><tr><td>Type</td><td>Brand</td><td>Price</td></tr>';
var i = 0;
debugger;
for (i = 0; i < jsonObj["products"].laptop.length; i++)
{
obj = jsonObj["products"].laptop[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
for (i = 0; i < jsonObj["products"].cellphone.length; i++)
{
obj = jsonObj["products"].cellphone[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
for (i = 0; i < jsonObj["products"].tablets.length; i++)
{
obj = jsonObj["products"].tablets[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
data += '</table>';
document.getElementById("demo").innerHTML = data;
}
}
http_request.open("GET", data_file, true);
http_request.send();
}
Question What is the way to fetch product list , i.e. products, cellphone and tablets ? Right now I have hardcoded that in order to fetch complete list of brands. Please advice. (I want to use plain javascript and not jquery)
Thanks!
It sounds like what you're missing is the "How do I iterate over an object when I don't know all the keys".
An object is a set of key, value pairs. You can use for/in syntax: for( var <key> in <object> ){} to get each key.
For your use case it might be something like:
var products = jsonObject['products'];
for( var productName in products ){
//productName would be "laptop", "cellphone", etc.
//products[productName] would be an array of brand/price objects
var product = products[productName];
for( var i=0; i<product.length; i++ ){
//product[i].brand
//product[i].price
}
}
In practice, I might use something a little less verbose, but this makes it easier to understand what is going on.
To achieve the expected i have used for loop and HTML DOM createElement() Method
var product_catalog = {
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
};
var output = document.querySelector('#product tbody');
function build(JSONObject) {
/**get all keys***/
var keys = Object.keys(JSONObject);
/**get all subkeys***/
var subkeys = Object.keys(JSONObject[keys]);
console.log(subkeys);
/**loop sub keys to build HTML***/
for (var i = 0, tr, td; i < subkeys.length; i++) {
tr = document.createElement('tr');
td = document.createElement('td');
td.appendChild(document.createTextNode(subkeys[i]));
tr.appendChild(td);
output.appendChild(tr);
}
};
build(product_catalog);
HTML:
Coepen URL for reference- http://codepen.io/nagasai/pen/xOOqMv
Hope this works for you :)
Look at this example:
var x = data.key1.children.key4;
var path = "data";
function search(path, obj, target) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
if (obj[k] === target)
return path + "['" + k + "']"
else if (typeof obj[k] === "object") {
var result = search(path + "['" + k + "']", obj[k], target);
if (result)
return result;
}
}
return false;
}
//Then for evry node that you need you can call the search() function.
var path = search(path, data, x);
console.log(path); //data['key1']['children']['key4']
I think this is what you're asking about, you can use Object.keys to get the properties of an object, then loop through them afterward.
var data = {
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
}
var typesOfProducts = Object.keys(data.products)
console.log(typesOfProducts)
document.getElementById('output').textContent = typesOfProducts.toString()
//Then, to loop through
var i = -1,
len = typesOfProducts.length
function handleProduct(productType) {
console.log("This is the " + productType + " data.")
console.log(data.products[productType])
}
while (++i < len) {
handleProduct(typesOfProducts[i])
}
<div id="output"></div>
It sounds like what you're looking for is just an array of the keys of the "products" object. Example:
Products: ["laptop", "cellphone", "tablets"];
If so, I would just run your json object through javascript's Object.keys() method.
var jsonObj = JSON.parse(http_request.responseText);
var products = Object.keys(jsonObj.products);
// products = ["laptop", "cellphone", "tablets"];
I'm trying to form a list from json data, see the example What I want is that it will show me the value just once when duplicate values occurs (2x Martini glass, I want it to return just one in the list), but leaves the array as is, i.e. still want to be able to hold all values in the array.
There'd sure be a simple way to achieve this, but i'm not finding it...
var data = {
"cocktails": [{
"name": "Bloody Mary",
"glass": "longdrink",
"ingredients": {
"main": "vodka",
"secondary": "tomato juice",
"addition": "tabasco"
}
}, {
"name": "Daiquiri",
"glass": "martini glass",
"ingredients": {
"main": "white rum",
"secondary": "lime juice",
"addition": "sugar syrup"
}
}, {
"name": "Martini",
"glass": "martini glass",
"ingredients": {
"main": "gin",
"secondary": "vermout",
"addition": "olive"
}
}]
}
$(data.cocktails).each(function () {
var output = "<ul><li>" + this.glass + "</li></ul>";
$('#placeholder').append(output);
});
Create an empty array:
var glasses = [];
Push all the glasses to it.
data.cocktails.forEach(function (el) {
glasses.push(el.glass);
});
Create a deduped array of glasses. This leaves the glasses array intact so you can use it again.
var dedupedGlasses = glasses.filter(function(elem, pos) {
return glasses.indexOf(elem) == pos;
});
Use join to create the HTML list.
var html = '<ul><li>' + dedupedGlasses.join('</li><li>') + '</li></ul>';
And add to the page.
$('#placeholder').append(html);
Demo
The you can use something like this to grab the count for each glasses type:
function getCount(arr) {
return arr.reduce(function(m, e){
m[e] = (+m[e]||0)+1; return m
}, {});
}
console.log(getCount(glasses)); // { longdrink=1, martini glass=2 }
Basically the same as #Andy, though slightly different.
var data = {
"cocktails": [{
"name": "Bloody Mary",
"glass": "longdrink",
"ingredients": {
"main": "vodka",
"secondary": "tomato juice",
"addition": "tabasco"
}
}, {
"name": "Daiquiri",
"glass": "martini glass",
"ingredients": {
"main": "white rum",
"secondary": "lime juice",
"addition": "sugar syrup"
}
}, {
"name": "Martini",
"glass": "martini glass",
"ingredients": {
"main": "gin",
"secondary": "vermout",
"addition": "olive"
}
}]
}
$('#placeholder').append('<ul><li>' + data.cocktails.map(function (cocktail) {
return cocktail.glass;
}).filter(function (glass, index, array) {
return array.indexOf(glass) === index;
}).join('</li><li>') + '</li></ul>');
On jsFiddle
I can just point to a solution where you need to define a new array
var cleanArr = []
$(data.cocktails).each(function () {
if($.inArray(this.glass, cleanArr) === -1) cleanArr.push(this.glass);
var output = "<ul><li>" + this.glass + "</li></ul>";
$('#placeholder').append(output);
});
console.log(cleanArr)
I like the way the array is created, that's why I'm posting this solution but it is not my idea --> taken from:
Remove Duplicates from JavaScript Array
Here is a working jsFiddle for you.
http://jsfiddle.net/Q74pj/1/
And here is what I did:
I used a new function calling uniqueArray to create a new associative array (which would be the quickest to iterate and fill).
You need to create a unique array, or sort it by drink and skip the duplicates.
function uniqueValues (arr) {
//if (arr.length < 2) return arr;
var retVal = {};
for (var i = 0; i < arr.length; i++) {
retVal[arr[i].glass] = arr[i];
}
return retVal;
}
then just use another way to iterate the associate array:
var uniqueArrayValues = uniqueValues(data.cocktails);
for (key in uniqueArrayValues) {
var output = "<ul><li>" + uniqueArrayValues[key].glass + "</li></ul>";
$('#placeholder').append(output);
}