I have a problem with the correct converting array to the form what I need from a graph plugin. I have a JSON which looks like below, from this file I have to count how many titles I have (see pic. 1). Hope you will understand from the pictures.
[
{
"name": "Mike Frost",
"title": "value_1",
"gender": "Male"
},
{
"name": "Hans Karl",
"title": "value_6",
"gender": "Male"
},
{
"name": "Kelly Clarkson",
"title": "value_3",
"gender": "Female"
},
...
]
This what I've got so far:
This what I need:
There is my script which counts values from JSON.
var employeeData = require('json!../path/to/json.json');
var obj = [];
for (var i = 0, j = employeeData.length; i < j; i++) {
if (obj[employeeData[i]['title']]) {
obj[employeeData[i]['title']]++;
}
else {
obj[employeeData[i]['title']] = 1;
}
}
One convenient way to do this is with a map (either a real Map if you're using ES2015, or an object we're using as a map if you're using ES5 or earlier). You build a new array and also keep track of the array entries in the map keyed by the value_X value:
var json = '[' +
' {' +
' "name": "Mike Frost",' +
' "title": "value_1",' +
' "gender": "Male"' +
' },' +
' {' +
' "name": "Hans Karl",' +
' "title": "value_6",' +
' "gender": "Male"' +
' },' +
' {' +
' "name": "Another Six",' +
' "title": "value_6",' +
' "gender": "Male"' +
' },' +
' {' +
' "name": "Kelly Clarkson",' +
' "title": "value_3",' +
' "gender": "Female"' +
' },' +
' {' +
' "name": "Another 3",' +
' "title": "value_3",' +
' "gender": "Female"' +
' },' +
' {' +
' "name": "Yet Another 3",' +
' "title": "value_3",' +
' "gender": "Female"' +
' }' +
']';
// Parse the JSON
var data = JSON.parse(json);
// The new array we'll build
var newArray = [];
// Our "map"
var map = Object.create(null);
// Loop the parsed data
data.forEach(function(entry) {
// Get the existing new entry if any
var mapEntry = map[entry.title];
if (mapEntry) {
// We have one, increase its `value`
++mapEntry.value;
} else {
// There isn't one, create it with a count of 1
// and save it to the array
mapEntry = map[entry.title] = {
label: entry.title,
value: 1
};
newArray.push(mapEntry);
}
});
// Done
console.log(newArray);
That can be written much more concisely, but I wanted to call out the individual parts of what I was doing.
In ES2015+:
const json = `[
{
"name": "Mike Frost",
"title": "value_1",
"gender": "Male"
},
{
"name": "Hans Karl",
"title": "value_6",
"gender": "Male"
},
{
"name": "Another Six",
"title": "value_6",
"gender": "Male"
},
{
"name": "Kelly Clarkson",
"title": "value_3",
"gender": "Female"
},
{
"name": "Another 3",
"title": "value_3",
"gender": "Female"
},
{
"name": "Yet Another 3",
"title": "value_3",
"gender": "Female"
}
]`;
// Parse the JSON
const data = JSON.parse(json);
// The new array we'll build
const newArray = [];
// Our map
const map = new Map();
// Loop the parsed data
data.forEach(entry => {
// Get the existing new entry if any
let mapEntry = map.get(entry.title);
if (mapEntry) {
// We have one, increase its `value`
++mapEntry.value;
} else {
// There isn't one, create it with a count of 1
// and save it to the array
mapEntry = {
label: entry.title,
value: 1
};
map.set(entry.title, mapEntry);
newArray.push(mapEntry);
}
});
// Done
console.log(newArray);
You can use Array.prototype.reduce and a hash table to group the data - see demo below:
var object=[{name:"Mike Frost",title:"value_1",gender:"Male"},{name:"Hans Karl",title:"value_6",gender:"Male"},{name:"Kelly Clarkson",title:"value_3",gender:"Female"},{name:"Mike Frost",title:"value_1",gender:"Male"},{name:"Hans Karl",title:"value_6",gender:"Male"}];
var result = object.reduce(function(hash){
return function(prev, curr){
if(hash[curr.title])
hash[curr.title].value++;
else {
hash[curr.title] = {label: curr.title, value: 1};
prev.push(hash[curr.title]);
}
return prev;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
You could iterate the array and count the occurence of the same titles.
var data = [{ "name": "Mike Frost", "title": "value_1", "gender": "Male" }, { "name": "Hans Karl", "title": "value_6", "gender": "Male" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, ],
result = data.reduce(function (hash) {
return function (r, a) {
if (!hash[a.title]) {
hash[a.title] = { label: a.title, value: 0 };
r.push(hash[a.title]);
}
hash[a.title].value++;
return r;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with Map
var data = [{ "name": "Mike Frost", "title": "value_1", "gender": "Male" }, { "name": "Hans Karl", "title": "value_6", "gender": "Male" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, { "name": "Kelly Clarkson", "title": "value_3", "gender": "Female" }, ],
result = data.reduce(
(map =>
(r, a) =>
(!map.has(a.title) && map.set(a.title, r[r.push({ label: a.title, value: 0 }) - 1]), map.get(a.title).value++, r)
)(new Map), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
I am a noob so please forgive me. I have the following JSON file:
`{ "Series": {"Next":
[ { "Name": "Cheese", "Price" : 2.50, "Location": "Refrigerated foods"},
{ "Name": "Crisps", "Price" : 3, "Location": "the Snack isle"},
{ "Name": "Pizza", "Price" : 4, "Location": "Refrigerated foods"},
{ "Name": "Chocolate", "Price" : 1.50, "Location": "the Snack isle"},
{ "Name": "Self-raising flour", "Price" : 1.50, "Location": "Home baking"},
{ "Name": "Ground almonds", "Price" : 3, "Location": "Home baking"} ]}`
I'm trying to reference the Name, Location and Price but it's now working. Here is the JavaScript code I am using:
.then(function(json) {
for(var i = 0; i < json.Next.length; i++) {
var listItem = document.createElement('li_prod');
listItem.innerHTML = '<strong_prod>' + json.Next[i].Name + '</strong_prod>';
listItem.innerHTML +=' can be found in ' + json.Next[i].Location + '.';
listItem.innerHTML +=' Cost: <strong_prod>£' + json.Next[i].Price + '</strong_prod>';
myList.appendChild(listItem);
}
that code is not picking up the Name, Location or price. How can I reference the data? Something like json.Series.Next[i].Name?
with the structure of your object it's more json.Series.Next instead of json.Next
var json = {
"Series": {
"Next":
[{
"Name": "Cheese",
"Price": 2.50,
"Location": "Refrigerated foods"
},
{
"Name": "Crisps",
"Price": 3,
"Location": "the Snack isle"
},
{
"Name": "Pizza",
"Price": 4,
"Location": "Refrigerated foods"
},
{
"Name": "Chocolate",
"Price": 1.50,
"Location": "the Snack isle"
},
{
"Name": "Self-raising flour",
"Price": 1.50,
"Location": "Home baking"
},
{
"Name": "Ground almonds",
"Price": 3,
"Location": "Home baking"
}
]
}
}
var myList = document.getElementById('my-list');
for (var i = 0; i < json.Series.Next.length; i++) {
var listItem = document.createElement('li_prod');
listItem.innerHTML = '<strong_prod>' + json.Series.Next[i].Name + '</strong_prod>';
listItem.innerHTML += ' can be found in ' + json.Series.Next[i].Location + '.';
listItem.innerHTML += ' Cost: <strong_prod>£' + json.Series.Next[i].Price + '</strong_prod>';
myList.appendChild(listItem);
}
<div id="my-list">
</div>
I would like to find number of items which has specific text using js filter method.
var num =
[
{
"name": "name1 ",
"category": "test"
},
{
"name": " name2",
"category": "test2"
},
{
"name": "name3",
"category": "cat3"
},
{
"name": "name 4",
"category": "cat 4"
}
];
num is an object;
Now, i want to find number of categories which has text 'cat'. So i want the result 2. How to get that using filter method.
here's how you can do it
var num =
[
{
"name": "name1 ",
"category": "test"
},
{
"name": " name2",
"category": "test2"
},
{
"name": "name3",
"category": "cat3"
},
{
"name": "name 4",
"category": "cat 4"
}
];
console.log( num.filter(i => i.category.indexOf("cat") === 0).length )
num is an object;
True, but specifically it's an array object.
You could use filter for this, but reduce would be the more appropriate option if you don't want the array of matching results:
var result = num.reduce(function(sum, entry) => sum + (entry.category.includes("cat") ? 1 : 0), 0);
Live Example:
var num =
[
{
"name": "name1 ",
"category": "test"
},
{
"name": " name2",
"category": "test2"
},
{
"name": "name3",
"category": "cat3"
},
{
"name": "name 4",
"category": "cat 4"
}
];
var result = num.reduce(function(sum, entry) {
return sum + (entry.category.includes("cat") ? 1 : 0);
}, 0);
console.log(result);
Or with ES2015+:
const num =
[
{
"name": "name1 ",
"category": "test"
},
{
"name": " name2",
"category": "test2"
},
{
"name": "name3",
"category": "cat3"
},
{
"name": "name 4",
"category": "cat 4"
}
];
const result = num.reduce((sum, entry) => sum + (entry.category.includes("cat") ? 1 : 0), 0);
console.log(result);
Or of course, a simple for loop.
This is fairly simple. In ES6 the solution would be this:
const countOfCats = num.filter(entry => entry.category.match('cat')).length;
Another way could be:
const countOfCats = num.filter(entry => entry.contains("cat")).length;
I'm trying to generate HTML table from JSON
The JSON provided is deeply nested. With the help of this thread How do I loop through deeply nested properties of a JavaScript object?, I am able to get the values of the JSON but I am confused on how to generate the HTML table
var districts = {
"district": [{
"ration": 4,
"states": [{
"name": "Louisiana",
"population": 42383,
"cities": [{
"name": "Cavalero"
}]
}]
}, {
"ration": 1,
"states": [{
"name": "Colorado",
"population": 980,
"cities": []
}, {
"name": "Arkansas",
"population": 58998,
"cities": []
}, {
"name": "Illinois",
"population": 59333,
"cities": [{
"name": "Kenwood"
}]
}]
}, {
"ration": 2,
"states": [{
"name": "Washington",
"population": 83984,
"cities": [{
"name": "Conestoga"
}, {
"name": "Whitehaven"
}, {
"name": "Dellview"
}]
}, {
"name": "West Virginia",
"population": 38034,
"cities": []
}]
}]
};
var i, district, j, states, k, cities;
for (i = 0; i < districts.district.length; i++) {
district = districts.district[i];
print(i + 1, ". District", i + 1, "consists of following states", "--- ration", district.ration);
for (j = 0; j < district.states.length; j++) {
states = district.states[j];
var said = (states.cities.length > 0) ? ("consists of following cities") : ("");
print(i + 1, ".", j + 1, states.name, said, "--- population", states.population);
for (k = 0; k < states.cities.length; k++) {
cities = states.cities[k];
print(" ", i + 1, ".", j + 1, ".", k + 1, cities.name);
}
}
}
Run this on Ideone
Any pointers/help/suggestions appreciated
You will need to generate a table, like this:
var districts = {
"district": [{
"ration": 4,
"states": [{
"name": "Louisiana",
"population": 42383,
"cities": [{
"name": "Cavalero"
}]
}]
}, {
"ration": 1,
"states": [{
"name": "Colorado",
"population": 980,
"cities": []
}, {
"name": "Arkansas",
"population": 58998,
"cities": []
}, {
"name": "Illinois",
"population": 59333,
"cities": [{
"name": "Kenwood"
}]
}]
}, {
"ration": 2,
"states": [{
"name": "Washington",
"population": 83984,
"cities": [{
"name": "Conestoga"
}, {
"name": "Whitehaven"
}, {
"name": "Dellview"
}]
}, {
"name": "West Virginia",
"population": 38034,
"cities": []
}]
}]
};
//Start of the table, including header
var table = '<table><thead><tr><th>Num</th><th>District</th><th>Population</th><th>Ration</th></tr></thead><tbody>';
//Num
for (var i = 0; i < districts.district.length; i++) {
//District
var district = districts.district[i];
//First row
table += '<tr><td>' + (i + 1) + '</td><td>District ' + district.ration + ' consists of the following states:</td><td></td><td>' + district.ration + '</td></tr>';
//States
var states = district.states;
for (var j = 0; j < states.length; j++) {
table += '<tr><td></td><td>' + (i + 1) + '.' + (j + 1) + ' ' + states[j] + ((states[j].cities && states[j].cities.length) ? ' consists of following cities:' : '') + '</td><td>' + states[j].population + '</td><td></td></tr>';
//Cities
if (states[j].cities) {
for (var k = 0; k < states[j].cities; k++) {
table += '<tr><td></td><td>' + (i + 1) + '.' + (j + 1) + '.' + (k + 1) + ' ' + states[j].cities[k].name + '</td><td></td><td></td></tr>';
}
}
}
}
//End of the table
table += '</tbody></table>';
and then add table somewhere into your html.
if you want to generate the desired output as on that link, you can use
<ol>
<li></li>
<li>
<ol><li></li></ol>
<li>
</ol>
instead of table. generate it using javascript. you can use below code to generate your ordered list which should be inserted on the main ordered list tag.
var district = districts.district;
function generateCities(cities){
cities.map((city) => {
return (
"<li>"+ city.name + "</li>"
)
})
}
function generateStates(states, generateCities){
states.map((stat) => {
return (
"<li>"+stat.name + " consists of following cities --- population " + stat.population + "</li>"
+"<ol>" + generateCities(stat.cities) + "</ol>"
)
});
}
function generateMyHtml(district, generateStates){
district.map((dist, index) => {
return (
"<li> District "+ index + "consists of following states --- ration " + dist.ration + "</li>"
+"<ol>" + generateStates(dist.states) + "</ol>"
)
});
};
hope this is helpful
I'm trying to create a JSON object for an API call which has the following format:
....
"Key": "Value",
"Package": {
"Dimensions": {
"UnitOfMeasurement": {
"Code": "IN",
"Description": "inches"
},
"Length": "20",
"Width": "25",
"Height": "30"
},
"PackageWeight": {
"UnitOfMeasurement": {
"Code": "Lbs",
"Description": "pounds"
},
"Weight": "80"
}
},
"Package": {
"Dimensions": {
"UnitOfMeasurement": {
"Code": "IN",
"Description": "inches"
},
"Length": "15",
"Width": "24",
"Height": "27"
},
"PackageWeight": {
"UnitOfMeasurement": {
"Code": "Lbs",
"Description": "pounds"
},
"Weight": "50"
}
},
"Key": "Value",
....
I should add as many "Package" objects as needed. However, I've tried doing this in many different ways but every time that I parse the variable to be used the first objects get overwritten and I end up with only the last object.
This is what I'm trying at the moment, still with no luck:
var lineItems = '{';
for (var i=0;i<inputObject.packages.length;i++) {
lineItems += '"Package": {"PackagingType": {"Code": "02","Description": "Rate"},"Dimensions": {"UnitOfMeasurement": {"Code": "IN","Description": "inches"},"Length": ' + inputObject.packages[i][0].toString() + ',"Width": ' + inputObject.packages[i][1].toString() + ',"Height": ' + inputObject.packages[i][2].toString() + '},"PackageWeight": {"UnitOfMeasurement": {"Code": "Lbs","Description": "pounds"},"Weight": ' + inputObject.packages[i][3].toString() + '}}';
if (i !== inputObject.packages.length-1) {
lineItems += ',';
}
}
lineItems += '}';
lineItems = JSON.parse(lineItems);
How about numbering your packages, ie:
for (var i=0;i<inputObject.packages.length;i++) {
lineItems+='"Package" + i : { ... }'
}
edit: to get required result (as an array - because it's not JSON), here's an example:
var a=[];
var b={"package": {"c":100,"d":200,"e":300}}
var c={"package": {"c":800,"d":700,"e":600}}
a.push(b);
a.push(c);
console.log(a);
Im experimenting with the espn public API and am trying to use their json to access NFL player information.
the json im accessing succesfully looks like:
{
"sports": [
{
"name": "football",
"id": 20,
"leagues": [
{
"name": "National Football League",
"abbreviation": "nfl",
"id": 28,
"groupId": 9,
"shortName": "NFL",
"athletes": [
{
"id": 14466,
"firstName": "Isa",
"lastName": "Abdul-Quddus",
"fullName": "Isa Abdul-Quddus",
"displayName": "Isa Abdul-Quddus",
"shortName": "I. Abdul-Quddus",
"links": {
"api": {
"athletes": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/14466"
},
"news": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/14466/news"
},
"notes": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/14466/news/notes"
}
},
"web": {
"athletes": {
"href": "http://espn.go.com/nfl/player/_/id/14466/isa-abdul-quddus?ex_cid=espnapi_public"
}
},
"mobile": {
"athletes": {
"href": "http://m.espn.go.com/nfl/playercard?playerId=14466&ex_cid=espnapi_public"
}
}
}
},
{
"id": 8645,
"firstName": "Hamza",
"lastName": "Abdullah",
"fullName": "Hamza Abdullah",
"displayName": "Hamza Abdullah",
"shortName": "H. Abdullah",
"links": {
"api": {
"athletes": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/8645"
},
"news": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/8645/news"
},
"notes": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/8645/news/notes"
}
},
"web": {
"athletes": {
"href": "http://espn.go.com/nfl/player/_/id/8645/hamza-abdullah?ex_cid=espnapi_public"
}
},
"mobile": {
"athletes": {
"href": "http://m.espn.go.com/nfl/playercard?playerId=8645&ex_cid=espnapi_public"
}
}
}
},
{
"id": 11910,
"firstName": "Husain",
"lastName": "Abdullah",
"fullName": "Husain Abdullah",
"displayName": "Husain Abdullah",
"shortName": "H. Abdullah",
"links": {
"api": {
"athletes": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/11910"
},
"news": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/11910/news"
},
"notes": {
"href": "http://api.espn.com/v1/sports/football/nfl/athletes/11910/news/notes"
}
} ........
]
}
]
}
],
"resultsOffset": 0,
"resultsLimit": 50,
"resultsCount": 3301,
"timestamp": "2013-01-06T19:30:17Z",
"status": "success"
}
and heres the html / javascript Im using:
$(document).ready(function(){
$.getJSON("http://api.espn.com/v1/sports/football/nfl/athletes?apikey=MY-API-KEY-HERE&_accept=application/json",
function(data){
$.each(data["sports"], function(i,item){
$("#infoDiv").append( [i] + " - " + item.name + "<br>" );
});
});
});
i can get this to display 0 - football but cant use something like
$.each(data["sports"]["leagues"]["athletes"], function(i,item){
$("#infoDiv").append( [i] + " - " + item.firstName + "<br>" );
to access the individual athlete data such as item.firstName , etc.
i keep getting the following error:
TypeError: data.sports.leagues is undefined
what am I missing? I'm using this same code structure successfully with a couple of other API's that provide json. the ESPN json is a little more complex in comparison though.
thanks for any light you can shed on this for me.
sports, leagues and athletes are arrays, for example: sports[0] is an object (the one with name='football')
You should iterate each like this (not tested):
$.each(data.sports, function(i,sport) {
$.each(sport.leagues, function(i,league) {
$.each(league.athletes, function(i,athlete) {
$("#infoDiv").append( [i] + " - " + athlete.firstName + "<br>" );
});
});
});
sports, leagues and athletes are arrays which you need to iterate.
for (var i=0; i<data.sports.length; i++) {
var sport = data.sports[i];
$("#infoDiv").append( [i] + " - " + sport.name + "<br>" );
for (var j=0; j<sport.leagues.length; j++) {
var league = sport.leagues[j];
$("#infoDiv").append( [i,j] + " - " + league.name + "<br>" );
for (var k=0; k<league.athletes.length; k++) {
var athlete = league.athletes[k];
$("#infoDiv").append( [i,j,k] + " - " + athlete.fullName + "<br>" );
}
}
}