Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have the following code. I'm trying to output each key value ("company" and "address") the different "city1, 2 ,3" object (list goes on and on in the real example). in to a <p> using javascript. I am feeling a bit lost since I've tried a lot of different ways but I can't get it to work. I believe it might be due to the structure. If it would only be one city there would be no problem.
var data = {
"city1":
[
{
"company": "Ica kvantum",
"address": "Orrgatan 3-5"
},
{
"company": "Hemköp",
"address": "Allegatan 26"
}
],
"city2":
[
{
"company": "Ica Nära",
"address": "Centrumvägen 7"
}
],
"city3":
[
{
"company": "Hora brothers kiosk",
"address": "Rövsgatan 43"
},
{
"company": "Microsoft",
"address": "Husvägen 38"
}
]
};
You can iterate the data object using for...in and then iterate the array inside with forEach.
var body = '';
for(var city in data) {
data[city].forEach(function(entry) {
body += '<p>' + entry.company + ', ' + entry.address + '</p>';
});
}
console.log(body);
If it's reasonable within your product requirements, you might consider using list elements rather than a simple <p>. Try to use the appropriate document.createElement methods rather than building a string. Something like:
var data = {
"city1": [{
"company": "Ica kvantum",
"address": "Orrgatan 3-5"
}, {
"company": "Hemköp",
"address": "Allegatan 26"
}],
"city2": [{
"company": "Ica Nära",
"address": "Centrumvägen 7"
}],
"city3": [{
"company": "Hora brothers kiosk",
"address": "Rövsgatan 43"
}, {
"company": "Microsoft",
"address": "Husvägen 38"
}]
};
var cityList = document.getElementById("city-list");
for (var cityName in data) {
if (data.hasOwnProperty(cityName)) {
var city = document.createElement("li");
var cityLabel = document.createElement("p");
cityLabel.textContent = cityName;
city.appendChild(cityLabel);
var companyList = document.createElement("ul");
city.appendChild(companyList);
var companies = data[cityName];
for (var i = 0; i < companies.length; ++i) {
var company = document.createElement("li");
company.textContent = companies[i].company + ": " + companies[i].address;
companyList.appendChild(company);
}
cityList.appendChild(city);
}
}
<ol id="city-list"></ol>
Similar to Ben's answer. I personally like plain for..in loops over foreaches in javascript, but its a preference.
var data = {
"city1":
[
{
"company": "Ica kvantum",
"address": "Orrgatan 3-5"
},
{
"company": "Hemköp",
"address": "Allegatan 26"
}
],
...
};
var html = "";
for(var city in data)
{
//you can append the city to the html here if you want
// html += "<h2>" + city + "</h2>";
for(var company in data[city])
{
for(var field in data[city][company])
{
html += "<p>" + field + ": " + data[city][company][field] + "</p>";
}
}
}
Related
Data source (JSON):
{
"photographers": [{
"name": "Mimi Keel",
"id": 243,
"city": "London",
"country": "UK",
"tags": ["portrait", "events", "travel", "animals"],
"tagline": "Voir le beau dans le quotidien",
"price": 400,
"portrait": "MimiKeel.jpg"
},
{
"name": "Ellie-Rose Wilkens",
"id": 930,
"city": "Paris",
"country": "France",
"tags": ["sports", "architecture"],
"tagline": "Capturer des compositions complexes",
"price": 250,
"portrait": "EllieRoseWilkens.jpg"
}
],
I am trying to loop trough the array contained in the key tags in the first photographers entry and display the all tags in a list item.
Heres what i got so far:
function fetchData() {
fetch("sample json file.json")
.then(response => response.json())
.then(data => {
console.log(data.photographers[0].tags[1])
// looping throw tags of a photographer
var output = "";
for (var i = 0; i <= data.photographers[0].tags.length; i++) {
for (keys in data.photographers[0].tags[i]) {
console.log(data.photographers[0].tags[i])
if (data.photographers[0].tags[i].hasOwnProperty(keys)) {
output += '<li>' +
'<a href="' + data.photographers[0].tags[i] +
'">' + data.photographers[0].tags[i] + '</a>' +
'</li>';
}
}
}
var update = document.getElementById('tags');
update.innerHTML = output;
})
}
fetchData();
I am open to any suggestion or correction of my code
Your loop can be made really simple. It has a couple of issues such as the one you mentioned, and another is dealing with multiple photographers and not just the first (Not sure if this is your actual use case):
Your code change: Remove your inner for loop as that's what duplicates everything:
for (var i = 0; i < data.photographers[0].tags.length; i++) {
console.log(data.photographers[0].tags[i])
}
Suggestion:
// same data given in the question
let data = { "photographers": [{ "name": "Mimi Keel","id": 243,"city": "London","country": "UK","tags": ["portrait", "events", "travel", "animals"],"tagline": "Voir le beau dans le quotidien","price": 400,"portrait": "MimiKeel.jpg" }, {"name": "Ellie-Rose Wilkens","id": 930,"city": "Paris","country": "France","tags": ["sports", "architecture"],"tagline": "Capturer des compositions complexes","price": 250,"portrait": "EllieRoseWilkens.jpg" }]};
// All photographers
for (let photographer of data.photographers) {
for (let tag of photographer.tags) {
console.log(tag);
// Here you get individual tag. Use it in your code like generating output.
}
}
// Just the first photographer
for (let tag of data.photographers[0].tags) {
console.log(tag);
// Here you get individual tag. Use it in your code like generating output.
}
First off, apologies if this is normally a simple thing, but I'm not particularly experienced in JS. I'm trying to make some graphs in Plotly.js for a work site that currently holds raw JSON. We have a JSON in the format:
stuff = [{"name": "shark", "location": "somewhere", "number":10},
{"name": "shark", "location": "somewhereelse", "number":50},
{"name": "shark", "location": "somewhere", "number":25},
{"name": "turtle", "location": "anotherplace", "number":1},
{"name": "elephant", "location": "greatplace", "number":50},
{"name": "elephant", "location": "greatplace", "number":75}
And I need the result to look like:
computed = [{"name":"shark", "location":"somewhere", "number":35},
{"name":"shark", "location":"somewhereelse", "number":50},
{"name":"turtle", "location":"anotherplace", "number":1},
{"name":"elephant", "location":"greatplace", "number":125}
Where all names are grouped by location and all numbers in that group are summed. It is then this computed JSON that I'll be using to graph with Plotly.js with some functions I have already built.
I think I can simplify the problem as:
forEach((item) => {
x.push(item['location']
y.push(y += stuff.number where stuff.location === x[-1])
}
But this also means I'll get the same number of rows as in stuff, just computed and graphed. I'm afraid I can't figure it out any further.
Any help would be muchly appreciated.
Simply looping out the original array, and adding the elements to a new array unless they are added already, or just adding the number will be the trick here. Here's the defined one:
var computed: any = [];
for(var element of stuff){
let computedElement = computed.find((ele: { location: string; }) => ele.location == element.location);
if (computedElement){
computedElement.number += element.number;
}
else{
computed.push(element);
}
}
First of all, json starts with {} and not []. Your object is a javascript object. I did a very long function below:
const stuffList = [
{"name": "shark", "location": "somewhere", "number":10},
{"name": "shark", "location": "somewhereelse", "number":50},
{"name": "shark", "location": "somewhere", "number":25},
{"name": "turtle", "location": "anotherplace", "number":1},
{"name": "elephant", "location": "greatplace", "number":50},
{"name": "elephant", "location": "greatplace", "number":75}
]
//extract all available location
const locations = stuffList.map( stuffItem => {
return stuffItem.location
})
const filteredStuff = locations.map( location => {
const number= stuffList.map( stuffItem => {
if(stuffItem.location === location) {
return stuffItem.number
}
return 0
}).reduce( (a, b) => a + b)// total all the numbers of mathcing
location
//get the first newStuffItem value equals to location
const [filteredStuffItem] = stuffList.map( stuffItem => {
if(stuffItem.location === location) {
return {
name: stuffItem.name,
location,
number
}
}
}).filter( stuffItem => {
return stuffItem?.location === location
})
return filteredStuffItem
})
const newStuffList = filteredStuff.filter((thing, index) => {
const _thing = JSON.stringify(thing);
return index === filteredStuff.findIndex(obj => {
return JSON.stringify(obj) === _thing;
})
});
console.log(newStuffList)
OR the magic by Deepak in javascript:
const stuff = [
{"name": "shark", "location": "somewhere", "number":10},
{"name": "shark", "location": "somewhereelse", "number":50},
{"name": "shark", "location": "somewhere", "number":25},
{"name": "turtle", "location": "anotherplace", "number":1},
{"name": "elephant", "location": "greatplace", "number":50},
{"name": "elephant", "location": "greatplace", "number":75}
]
var computed = [];
for(var element of stuff){
let computedElement = computed.find((ele) => ele.location == element.location);
if (computedElement){
computedElement.number += element.number;
}
else{
computed.push(element);
}
}
console.log(computed)
Sorry for not replying to this sooner, and thanks to those who commented. For whatever reason I couldn't get the other suggested solutions to work but I seeing another perspective on the logic needed helped me figure it out.
if (!label.includes(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])) {
label.push(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])
x.push(item['date'])
y.push(item['sum'])
} else {
var indx = label.indexOf(item['specimen'] + ':' + item['well_label'] + ':' + item['run'] + ':' + item['group'])
let summed = y[indx] + item['sum']
y.splice(indx, 1, summed)
So essentially this created something akin to a compound key, and pushes the initial data to add it to the label list and then the data to the relevant lists. If that compound key appears again then the value is just updated with the splice method.
Only issue is that because these lists are not linked in anyway than the data being input to them, there is a rare chance of the right label and data not matching up but after a lot of testing I have sorted that out and it does work.
Again thanks to the previous commenters that helped.
I'm trying to write up a console.log under Tests in Postman to do two things
1- Count how many types/Unique "ShipmentStatus" were received in the response body (In-Process,Shipped, & Rejected)
2 - How how many of each ShipmentStatus we received for example (4 Orders In-Process 5 Orders in Complete)
How can I accomplish 1 and 2 to show up in my console.log?
"Orders": [
{
"id": 544789,
"Company": {
"ClientName": "Therese",
},
"Shipping": {
"Address": "Street,",
},
"userId": "1413260",
"ShipmentStatus": "In-Process"
},
{
"id": 544787,
"Company": {
"ClientName": "Therese",
},
"Shipping": {
"Address": "Street,",
},
"userId": "1413260",
"ShipmentStatus": "Shipped"
},
{
"id": 544786,
"Company": {
"ClientName": "Therese",
},
"Shipping": {
"Address": "Street,",
},
"userId": "1413260",
"ShipmentStatus": "Rejected"
},
I'm able to obtain the total records received by doing the following
console.log("Total Orders : " + response.Orders.length);
You could do something very quick and dirty like this, if all you want to see is those values logged out to the Console:
console.log(`Total Orders: ${pm.response.json().Orders.length}`)
var counts = {};
for (var i = 0; i < pm.response.json().Orders.length; i++) {
counts[pm.response.json().Orders[i].ShipmentStatus] = 1 + (counts[pm.response.json().Orders[i].ShipmentStatus] || 0);
}
console.log(counts)
I extended your JSON response so that you could see what it would look like if you had more items:
You can do it using object:
var buffer = {}
var orders = pm.response.json().Orders;
orders.forEach(function(item) {
var id = item.ShipmentStatus;
if(buffer[id]) buffer[id]++
else buffer[id] = 1;
})
for(var status in buffer)
{
console.log(status + ":" +buffer[status])
}
console.log(Object.keys(buffer).length+" unique values")
So you understood me.
I'm having some issues displaying multiple JSON arrays if anybody could help,
i would appreciate it.
JSON
{
"houseOne": [
{
"name": "John Clarke",
"age": 22,
"dob": "19-11-90"
},
{
"name": "Mitch Woodier",
"age": 20,
"dob": "23-10-92"
},
{
"name": "Mavis Waddingham",
"age": 21,
"dob": "10-11-91"
}
],
"houseTwo": [
{
"name": "Luke Woodier",
"age": 22,
"dob": "19-11-90"
},
{
"name": "Rob Clarke",
"age": 20,
"dob": "23-10-92"
},
{
"name": "Alex Gayfag",
"age": 21,
"dob": "10-11-91"
}
]
}
Javascript
<script type="text/javascript">
function ajaxRequest(url)
{
var request = new XMLHttpRequest();
// Work around for IE caching problem
if (url.indexOf('?') < 0) {
today = new Date();
url += '?' + today.getTime();
}
request.open("GET", url, false);
request.setRequestHeader("Cache-Control", "no-cache");
request.send();
return request.responseText;
}
var data = ajaxRequest("results.json");
var houses = JSON.parse(data);
function displayJson() {
var myDiv =document.getElementById("content");
for (house = 0; house < 3; house++) {
var home = houses.houseOne[house];
myDiv.innerHTML += houseDetails(home,house);
}
}
function houseDetails(home,houseNumber){
var myHTML = "<h1>House Mate "+ (houseNumber +1)+"</h1>";
myHTML += "<table>";
myHTML += "<tr><th>Name</th><th>Age</th><th>D.O.B</th></tr>";
myHTML += "<tr>";
myHTML += "<td>";
myHTML += home.name;
myHTML += "</td>";
myHTML += "<td>";
myHTML += home.age;
myHTML += "</td>";
myHTML += "<td>";
myHTML += home.dob;
myHTML += "</td>";
myHTML += "</table>";
return myHTML
}
</script>
Basically I can get it to display houseOne as a table but I can't get it to display both houseOne and houseTwo, I hope this is clear I'm not very good with web dev.
Regards,
Dean
In your displayJson() function you're only referencing house.houseOne
var home = houses.houseOne[house];
Here's an updated version (I've added jQuery too) http://jsfiddle.net/XzZUR/1/
JSON
var houses = {
"houseOne": [{
"name": "John Clarke",
"age": 22,
"dob": "19-11-90"
}, {
"name": "Mitch Woodier",
"age": 20,
"dob": "23-10-92"
}, {
"name": "Mavis Waddingham",
"age": 21,
"dob": "10-11-91"
}],
"houseTwo": [{
"name": "Luke Woodier",
"age": 22,
"dob": "19-11-90"
}, {
"name": "Rob Clarke",
"age": 20,
"dob": "23-10-92"
}, {
"name": "Alex Gayfag",
"age": 21,
"dob": "10-11-91"
}]
};
Javascript
function displayJson() {
var myDiv = $("#content");
$.each(houses, function(){
var house = this;
$(house).each(function(key){
myDiv.append(houseDetails(this,key));
})
});
}
I'd recommend not using synchronous ajax request, it would be better to use a callback.
You could itterate through every house object like so:
function displayJson() {
var i,h,ret=[];
var myDiv =document.getElementById("content");
// houseone and housetwo
for (h in houses) {
// houseone and housetwo are arrays: [house,house,house]
// for every house in this array do:
for(i=0;i<houses[h].length;i++){
var home = houses[h][i];
ret.push(houseDetails(home,i));
}
}
//setting innerHTML is resource intensive
// no reason to do this within a loop.
myDiv.innerHTML=ret.join("");
}
I am trying to incorporate a micro template into a plugin I am building. I have gotten everything good and all, but I am having issues when it comes to the nested array in the data. Thank you very much in advance for your help. Here is the stripped code:
var locations = [{
"name": "Disneyland California",
"address": "1313 North Harbor Boulevard"
},
{
"name": "Walt Disney World Resort",
"address": "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[0],
foo: "bar"
}],
template = "Shipping From:<br><b>{{location.name}}, {{foo}}",
attachTemplateToData;
attachTemplateToData = function(template, data) {
var i = 0,
len = data.length,
fragment = '';
function replace(obj) {
var t, key, reg;
for (key in obj) {
reg = new RegExp('{{' + key + '}}', 'ig');
t = (t || template).replace(reg, obj[key]);
}
return t;
}
for (; i < data.length; i++) {
fragment += replace(data[i]);
}
console.log(fragment);
};
attachTemplateToData(template, tmplData);
Logs:
bar,{{location.name}}
As you can see in the console.log that 'foo' comes out just fine, but I also need to get the 'location.name' ("Disneyland California") to render as well. I know its going to be a nested loop, but I cannot for the life of me figure out the syntax. BTW, the templating solution came from here: http://net.tutsplus.com/tutorials/javascript-ajax/create-a-makeshift-javascript-templating-solution/
Thanks!
EDIT:::
I am looking to make ANY property of the locations object able to be put into the template. So for instance if the user decided they want to add locations.city or locations.foo to the array, then in the template, they would just have to go {{location.city}} or {{location.foo}}.
I HAVE been able to achieve this through the use of jQuery's tmpl plugin, but I don't need all of what that has to offer. I would like a VERY stripped version like I have, to only deal with the said instances. Here is what I did with the tmpl plugin (which works):
tmplData = [{
locations: settings.locations[i]
}];
var tmplMarkup = "Shipping From:<br><b>${locations.name}, ${locations.city}, ${locations.state}</b>";
$.template("deTemplate", tmplMarkup);
$.tmpl("deTemplate", tmplData).appendTo("#deResults");
What you need is to change template recognition to match not only {{prop}} in your matching code , but also {{prop.something}}
you can do this adding another if statement with new regexp.
instead of this:
var locations = [{
"name": "Disneyland California",
"address": "1313 North Harbor Boulevard"
},
{
"name": "Walt Disney World Resort",
"address": "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[0],
foo: "bar"
}],
template = "Shipping From:<br><b>{{location.name}}, {{foo}}",
attachTemplateToData;
Try this:
var locations = [{
name: "Disneyland California",
address: "1313 North Harbor Boulevard"
},
{
name: "Walt Disney World Resort",
address: "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[0].name,
foo: "bar"
}],
template = "Shipping From:<br><b>{{location}}, {{foo}}",
attachTemplateToData;
Really it is just the .name needs to be about 4 lines up! :)
Thank you for your input vittore, I have finally figured out the code. Here is the extra if statement and regEx that I needed to have, also I found that I need the .hasOwnProperty function in there too:
for(subKey in obj[key]){
if (obj[key].hasOwnProperty(subKey)) {
reg = new RegExp('{{'+key+'.'+subKey+'}}');
t = (t || template).replace(reg, obj[key][subKey]);
}
}
Here is the completed code:
var locations = [{
"name": "Disneyland California",
"address": "1313 North Harbor Boulevard"
},
{
"name": "Walt Disney World Resort",
"address": "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[1],
foo: "bar"
}],
template = "Shipping From:<br><b>{{location.address}}, {{foo}}",
attachTemplateToData;
attachTemplateToData = function(template, data) {
var i = 0,
j = 0,
len = data.length,
fragment = '';
function replace(obj) {
var t, key, subKey, subSubKey, reg;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
reg = new RegExp('{{' + key + '}}', 'ig');
t = (t || template).replace(reg, obj[key]);
for(subKey in obj[key]){
if (obj[key].hasOwnProperty(subKey)) {
reg = new RegExp('{{' + key + '.' + subKey + '}}','ig');
t = (t || template).replace(reg, obj[key][subKey]);
}
}
}
}
return t;
}
for (; i < data.length; i++) {
fragment += replace(data[i]);
}
console.log(fragment);
};
attachTemplateToData(template, tmplData);