I'm new to Javascript so this might be a naive question. I have following json response from the server. I want to select the values of Alpha, Bravo, Charlie and Delta.
data = {"Agent Contribution (Incl Rev)":{"Alpha":33245.0,"Bravo":26618.0,"Charlie":22376.0,"Delta":15831.0}}
I can select values in the console by doing data["Agent Contribution (Incl Rev)"]. However when I try this in JavaScript (code editor) by doing console.log(data["Agent Contribution (Incl Rev)"]), it returns null.
Try it this way:
data = {
"Agent Contribution (Incl Rev)": {
"Alpha": 33245.0,
"Bravo": 26618.0,
"Charlie": 22376.0,
"Delta": 15831.0
}
}
console.log(`
${data['Agent Contribution (Incl Rev)'].Alpha}
${data['Agent Contribution (Incl Rev)'].Bravo}
${data['Agent Contribution (Incl Rev)'].Charlie}
${data['Agent Contribution (Incl Rev)'].Delta}
`);
If I understood the question, you are looking for values of Alpha ,Bravo. if yes,Try this
var data = {"Agent Contribution (Incl Rev)":{"Alpha":33245.0,"Bravo":26618.0,"Charlie":22376.0,"Delta":15831.0}}
var selectedVal = Object.keys(data).map(function (prop) {
return Object.keys(data[prop]).map(function(val){
return data[prop][val]
})
})
console.log(selectedVal,"selectedVal")
There are many ways to access object properties, one of which is listed below:
First you extract keys using Object.keys which returns array of keys to you of a given object. You then iterate through each array item which is key of the given object and access using object property that key. Solutions like this would avoid all the potential typos in accessing key naming.
Its not a comprehensive solution to cover all edge cases but with keys having spaces, these is pretty good technique to cover all the bases. One thing to note here is key access is not in sorted order.
var data = {
"Agent Contribution (Incl Rev)": {
"Alpha": 33245.0,
"Bravo": 26618.0,
"Charlie": 22376.0,
"Delta": 15831.0
}
}
Object.keys(data).map(obj => {
console.log(data[obj]);
console.log(data[obj].Alpha);
console.log(data[obj].Bravo);
});
Related
I have a JSON data set as follows:
{
"content":[],
"layout":[],
"trail":[
{
"content":[
{
"type":"image",
"media":[
{
"type":"image/jpg",
"width":593,
"height":900,
"url":"https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg",
"flickr":{
"flickr-post":"https://www.flickr.com/photos/riketrs/48208920877",
"flickr-album":"https://www.flickr.com/photos/riketrs/albums/72157709130951466"
}
}
]
},
{
"type":"image",
"media":[
{
"type":"image/jpg",
"width":1600,
"height":900,
"url":"https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg",
"flickr":{
"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532",
"flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"
}
}
]
}
],
"colors":{
"c0":"#1e1e1d",
"c1":"#78736f",
"c2":"#b2a89f"
}
}
]
}
I would like to console.log the "url" key for each of the images shown here.
(https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg and https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg)
I tried some code but I'm very new to JSON in general, I've looked at some other answers to do with JSON but I'm not quite sure how to achieve what I want.
JSFiddle: https://jsfiddle.net/fj6qveh1/1/
I appreciate all advice, including links to other answers that I potentially missed.
Thank you!
url is a property of an object. There can be many of these in a media array. (This data only shows one object per array.) media itself is an property of objects inside the content array.
Use map, and flatMap.
map to return the URL values from the objects in media, and flatMap to return a flat array of the nested arrays returned by map.
const data={content:[],layout:[],trail:[{content:[{type:"image",media:[{type:"image/jpg",width:593,height:900,url:"https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/riketrs/48208920877","flickr-album":"https://www.flickr.com/photos/riketrs/albums/72157709130951466"}}]},{type:"image",media:[{type:"image/jpg",width:1600,height:900,url:"https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532","flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"}},{type:"image/jpg",width:1600,height:900,url:"https://live.dummyimage.com/2817/dummy.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532","flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"}}]}],colors:{c0:"#1e1e1d",c1:"#78736f",c2:"#b2a89f"}}]};
const content = data.trail[0].content;
const urls = content.flatMap(obj => {
return obj.media.map(inner => inner.url);
});
console.log(urls)
The easiest way is to use map function. Given that you are very new to programming (the solution has little to do with JSON itself, since the first step is to parse JSON string to a JavaScript object), it would be better if you try yourself. But you start with
let urls = trail["content"].map(x => x["media"][0]["url"])
for more about map function look here
There is a table in the table so for each table:
for(let i in trail){
var content = trail[i]["content"];
content.forEach(content => content.media.forEach(media => console.log(media.url)))
}
To access object properties, you can use a dot (.), and to access an array element, you use its index in square brackets ([]). So you just keep repeating these steps as necessary until you get to the content you're looking for.
Here's how that looks on a simplified version of your object, using the forEach method of arrays to apply a custom function to each item in the content array:
const json = getJson();
json.trail[0].content.forEach(item=>console.log(item.media[0].url));
function getJson(){
let obj = {
"trail": [{
"content": [
{ "media": [{ "url":"image #65535/48208920877_e6b234d3ea_c_d.jpg" }]},
{ "media": [{"url":"image #2817/33807326532_91013ef6b1_h_d.jpg"}]}
]
}]
};
return obj;
}
Suppose I have some JSON like below:
[
{
"date": "2020-12-25",
"total_cases": 469482.0,
"new_cases": 2260.0,
"new_cases_smoothed": 2115.571,
"total_deaths": 9816.0,
"new_deaths": 63.0,
"new_deaths_smoothed": 80.857,
"total_cases_per_million": 2125.388,
"new_cases_per_million": 10.231,
"new_cases_smoothed_per_million": 9.577,
"total_deaths_per_million": 44.438,
"new_deaths_per_million": 0.285,
"new_deaths_smoothed_per_million": 0.366,
"new_tests": 54649.0,
"total_tests": 6482889.0,
"total_tests_per_thousand": 29.349,
"new_tests_per_thousand": 0.247,
"new_tests_smoothed": 38118.0,
"new_tests_smoothed_per_thousand": 0.173,
"positive_rate": 0.056,
"tests_per_case": 18.0,
"tests_units": "tests performed"
},
{
"date": "2020-12-26",
"total_cases": 471335.0,
"new_cases": 1853.0,
"new_cases_smoothed": 2006.714,
"total_deaths": 9874.0,
"new_deaths": 58.0,
"new_deaths_smoothed": 77.714,
"total_cases_per_million": 2133.777,
"new_cases_per_million": 8.389,
"new_cases_smoothed_per_million": 9.085,
"total_deaths_per_million": 44.701,
"new_deaths_per_million": 0.263,
"new_deaths_smoothed_per_million": 0.352,
"new_tests": 40953.0,
"total_tests": 6523842.0,
"total_tests_per_thousand": 29.534,
"new_tests_per_thousand": 0.185,
"new_tests_smoothed": 37101.0,
"new_tests_smoothed_per_thousand": 0.168,
"positive_rate": 0.054,
"tests_per_case": 18.5,
"tests_units": "tests performed"
},
{
"date": "2020-12-27",
"total_cases": 473309.0,
"new_cases": 1974.0,
"new_cases_smoothed": 2048.714,
"total_deaths": 9929.0,
"new_deaths": 55.0,
"new_deaths_smoothed": 76.714,
"total_cases_per_million": 2142.714,
"new_cases_per_million": 8.936,
"new_cases_smoothed_per_million": 9.275,
"total_deaths_per_million": 44.95,
"new_deaths_per_million": 0.249,
"new_deaths_smoothed_per_million": 0.347,
"new_tests": 33270.0,
"total_tests": 6557112.0,
"total_tests_per_thousand": 29.685,
"new_tests_per_thousand": 0.151,
"new_tests_smoothed": 36539.0,
"new_tests_smoothed_per_thousand": 0.165,
"positive_rate": 0.056,
"tests_per_case": 17.8,
"tests_units": "tests performed"
},
{
"date": "2020-12-28",
"new_tests": 32205.0,
"total_tests": 6589317.0,
"total_tests_per_thousand": 29.83,
"new_tests_per_thousand": 0.146,
"new_tests_smoothed": 36172.0,
"new_tests_smoothed_per_thousand": 0.164,
"tests_units": "tests performed"
}
]
Out of this array of records in the JSON, I'm looking to grab the most recent instance of "total_cases". Here is the JavaScript I wrote to satisfy this:
const total_cases = (data[data.length - 1].total_cases);
Obviously, this doesn't work, because the last record in the array doesn't contain an instance of the "total_cases" key. I'm fetching from the source using HTTP GET, and it is updated daily, so sometimes the latest record has the keys I'm looking for, but other times I get a TypeError.
My question is if there is any way to find the index of the latest record that has a particular key I'm looking for, when the JSON has some inconsistencies like this. The alternative is to say hell with it and look for another source. I'm considering that option, because this is too much of a hassle to work with, but I'm still curious as to what could be done. Hope that makes sense.
You could reverse the array and then use the Array.find method.
const total_cases = data
.slice() // Since reverse() changes the array in place, we need a copy of the original array
.reverse()
.find(record => record.total_cases !== undefined)
.total_cases;
A possible way to do that would be by reversing the array and then use Array.prototype.find() to search for the most recent record with total cases.
data.reverse().find(r => r.total_cases);
You can do something like this, that I find easy to understand for you and for the next dev reading your code
data
.sort((i1, i2) => i1.date > i2.date ? -1 : 1)
.filter(item => Boolean(item.total_cases))
[0].total_cases
I have the following function, which is called when a google forms is submitted. I'm trying to concatenate all answers into a single array that's gonna be used latter:
function onFormSubmit(e) {
var respostas = e.namedValues;
for(item in respostas){
rp = rp.concat(respostas[item]);
}
}
But I would like to drop the timestamp that comes together with the answers. I can access it with respostas['Timestamp'], but I can't find a way to drop or ignore it. The documentation didn't help much.
var cp = [];
function onSubmitForm(e) {
var respostas = e.namedValues;
for (var name in respostas) {
if (respostas.hasOwnProperty(name) {
if (name !== 'Timestamp') {
cp.push(respostash[name]);
}
}
}
}
This is what I would suggest. Using concat to add an item is overkill, you can just push it. Also is a good practice when you are looping over object properties to make sure that they are its own properties of that object, not inherited from prototype. You can read more about it here
You can check the name of the property before concatenate it with the rest.
If the key item equals Timestamp (the undesired property) just skip the current loop.
for(item in respostas) {
if (item === 'Timestamp') {
continue;
}
rp = rp.concat(respostas[item]);
}
EDIT: Based on comments, OP attests that item in the for..in loop is a integer, but, unless his/her code differs radically from the docs, the variable should hold strings, not numbers.
var respostas = {
'First Name': ['Jane'],
'Timestamp': ['6/7/2015 20:54:13'],
'Last Name': ['Doe']
};
for(item in respostas) {
console.log(item);
}
e.namedValues returns a JSON Object with custom keys.
var jsonObj = e.namesValues;
/* e.namedValues returns data like this...
{
"test1": "testval1",
"test2": "testval2",
"test3": "testval3",
}
*/
for(item in respostas){
Logger.log(item); //Key
Logger.log(respostas[item]); //Value
}
This should let you access the key or value on the items in respostas.
The accepted answer is better as it does more to help the user to fix their exact problem, however, I will leave this here for future users in case they want to understand how to access the variables in the object that Google Apps Scripts returns.
I have the response in the following format after doing groupby in solr query. I am using solr version 3.5
"grouped":{
"channel_id":{
"matches":48,
"ngroups":26,
"groups":[{
"groupValue":"204",
"doclist":{"numFound":1,"start":0,"docs":[
{
"channel_name":"ZeeTv",
"channel_num":4,
"title":"The Name",
"channel_id":"204"
}},
{
"groupValue":"166",
"doclist":{"numFound":2,"start":0,"docs":[
{
"channel_name":"Sony",
"channel_num":2,
"title":"The Name",
"channel_id":"166",
{
"channel_name":"Sony",
"channel_num":2,
"title":"The Puzzle",
"channel_id":"166"
}}]}}
I am taking the response in an array in the following way :
for(var chl in data.grouped.channel_id.groups) {
config['playlist'].push(data.grouped.channel_id.groups[chl]['doclist']['docs']);
}
Thus an individual array of each groupValue is formed. The struture of the array is:
"0"=>{"0"=>"value"},"1"=>{"0"=>"result1","1"=>"result2"}
But i want to change the key name i.e. "0","1" to the groupValue from the response while creating an array so that i can do config['playlist']['166'] to check all the shows for this channel_id from the array. Can this be done and if so how. I am expecting the following :
"204"=>{"0"=>"value"},"166"=>{"0"=>"result1","1"=>"result2"}
Also if possible can the solr query be made such that the channel_num in the response comes in ascending order i.e. first result for channel_num 2 and then 4. I have done groupby:channel_id
What about that?
for(var chl in data.grouped.channel_id.groups) {
config['playlist'][data.grouped.channel_id.groups[chl].groupValue] = data.grouped.channel_id.groups[chl]['doclist']['docs'];
}
Push is there to add an element at the end of an array. But any Javascript object is just a hash table, so you can use it that way.
By the way, you can make the code simpler with a for each :
for each(var chl in data.grouped.channel_id.groups) {
config['playlist'][ch1.groupValue] = ch1['doclist']['docs'];
}
Pikrass has answered correctly... as far as ordering with channel_num is concerned try adding the following in your query:
&sort=channel_num asc
I have an array like this (with just over 3000 objects instead of the 3 here):
items = [{name:'charlie', age:'16'}, {name:'ben', age:'18'}, {name:'steve', age:'18'}]
What's the best way to return an array with just the objects of people who are 18? So I want:
items = [{name:'ben', age:'18'}, {name:'steve', age:'18'}]
The best I can think of is this (using jQuery):
newArray = []
$.each(items, function(index, item) {
if(item.age=='18') {
newArray.push(item)
}
})
Considering that there's 3000 thousand objects, and also that I'll be doing that comparison up to fifty times in one go, that's a lot of looping. Is there a better way?
You can use pure javascript
var wanted = items.filter( function(item){return (item.age==18);} );
And if your browser does not support the 1.6 version of javascript you can find an implementation of the filter method at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
Update
Speedwise there is a huge varying (had an error in the test) difference from a normal loop (depending on browser).. Have a look at this little test i made at http://jsperf.com/array-filter-vs-loop/3
Get matched item and items using find() and filter() method
If you want first matched single item, use find() method which returns single object.
If you want all matched , use filter() method which returns array of objects.
let items = [{name:'charlie', age:'16'},
{name:'ben', age:'18'},
{name:'steve', age:'18'}]
let all = items.filter(item=> item.age==='18')
console.log(all);
let single = items.find(item=> item.age==='18')
console.log(single);
If you're going to do the search often it may be best to keep a version of your data in a form that is quick to access.
I've used underscore.js (http://documentcloud.github.com/underscore/) to make it easy for myself, but this code here will create an object that holds your data indexed by the age field.
You end up with something that looks like this:
{
"16": [
{
"name": "charlie",
"age": "16"
}
],
"18": [
{
"name": "ben",
"age": "18"
},
{
"name": "steve",
"age": "18"
}
]
}
The code:
var itemsByAge = _(items).reduce(function(memo, item) {
memo[item.age] = memo[item.age] || [];
memo[item.age].push(item);
return memo;
}, {});
alert(JSON.stringify(itemsByAge["18"]));
No matter which method you choose (items.filter or any "query language" for json), a for loop is inevitable.
If performance is a concern, I would recommend you to use pure javascript instead of libraries like jQuery which will add overheads to the whole processing as is evident here.
Thus, your code would look like:
var newArray = [];
for(var i=0;i<items.length;i++) {
var item = items[i];
if(item.age == '18') {
newArray.push(item);
}
});
making use of javascript magnificent function eval() which evaluates string as code at runtime, we can define a prototype method for Array type
Array.prototype.where = function (query) {
var newArray = [];
for(var i=0; i<this.length; i++) {
var item = this[i];
if(eval( "item" + query )) {
newArray.push(item);
}
}
return newArray;
};
and use it with any array, passing the query as string
var newArray= items.where('.age >= 18');
Use the filter method of the array, it calls the provided callbackfunction once for each element in an array.
array.filter(<callbackfucntion>[, <Object to use>])
once i had such problem and i solved it like this
1- create an array of array
2- each index create an Index record
e.g.
var pAry=[];
var cAry=[{name:'ben', age:'18'}, {name:'steve', age:'18'}]
pAry[17]=cAry;
This way when u require person with age 18, you will get on index 17.