I've tried to write a script for parsing a JSON file stored in the server and returning its pairs of key/values into list items containing the relevant attributes in colon-separated format.
I've attempted to do it by using native javascript commands. Although the file is parsed successfully and you can realize that by calling for distinct elements with reference numbers (eg. myObject.pets[1].animal or myObject.pets.length) the loop inside the code that is supposed to capture all items is not working.
Here is the code
<!DOCTYPE html>
<html>
<body>
<ul id="animals"></ul>
<script>
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObject = JSON.parse(this.responseText);
var finalString = "";
for (i in myObject.pets.length) {
var currentItem = "<li>" + myObject.pets[i].animal + ": " + myObject.pets[i].name + "</li>";
var finalString = finalString.concat(currentItem);
}
document.getElementById("animals").innerHTML = finalString;
}
};
xmlhttp.open("GET", "animals.json", true);
xmlhttp.send();
</script>
</body>
</html>
The JSON file
>animals.json
{
"pets":[
{ "animal":"dog", "name":"Fido" },
{ "animal":"cat", "name":"Felix" },
{ "animal":"hamster", "name":"Lightning" }
]
}
and the expected outcome
<li>dog: Fido</li>
<li>cat: Felix</li>
<li>hamster: Lightning</li>
Javascript's for...in functionality loops through the properties of an object, it doesn't increment a variable up to a limit like you expect. Either use it as
for (let i in myObject.pets) which will give i the value of each key in the pets object (with indices in an array acting as keys in an object).
Or since this is a standard array you can do plenty of things with it. You could loop through it normally with for (let i = 0; i < myObject.pets.length; i++) but based on what you're trying to do I recommend reduce.
I've included a demo which uses reduce to get the finalString in a modern JS way. If you want to stick with your current function though, make sure you don't redefine finalString with var finalString in your loop which you are currently doing. My demo doesn't set the innerHTML of an element and instead writes it to the document, but you can do whatever you want with the finalString.
let apiResult = '{"pets":[{ "animal":"dog", "name":"Fido" }, { "animal":"cat", "name":"Felix" }, { "animal":"hamster", "name":"Lightning" } ] }';
let jsonResult = JSON.parse(apiResult);
let finalString = jsonResult.pets.reduce((total, current) => {
return total.concat("<li>" + current.animal + ": " + current.name + "</li>");
}, "");
document.write(finalString);
I really like #Matthew's answer. Here's a version using map instead of reduce, that makes the code more verbose, but I my opinion also easier to read.
const petsString = '{"pets": [{"animal": "dog", "name": "Fido"}, {"animal": "cat", "name": "Felix"}, {"animal": "hamster", "name": "Lightning"}]}'
const petsArray = JSON.parse(petsString).pets
const petsHtml = petsObject
.map(pet => `<li>${pet.animal}: ${pet.name}</li>`)
.join("")
document.write(petsHtml)
Related
I'm working with adobe CEP 10, I need to get a specific value from an array with the find option in the JSX file. but JSX says find is not a function. how do I get a specific value from an array
Here is a pretty meaningless kindergarten style snippet but anyway:
var array = ["foo", "bar", "Alice", "Bob"];
var found = "";
var sample = prompt("Find for:");
var counter = 0;
while (counter<array.length) {
if (array[counter] == sample) {
found = sample;
break;
}
counter++;
}
if (found != "") {
alert("'" + found + "' was found in the array in position " + (counter+1));
} else {
alert("Nothing was found");
}
In:
Out:
Something like this can be done in various ways. Via indexOf() or includes(), etc. It depends on your task.
I have a simple array that I'm having the hardest time trying to sort. I'm thinking maybe it's because of the time format, so I'm unsure how to reference it or how I could sort the time, in this array format, so that I can sort it later.
//function created to input values
function put(key, value, obj) {
obj[key] = value;
return obj
}
//loads the document from ajax call
function loadDoc() {
//ajax call
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = xhttp.responseText;
//input data from webpage into dom element
document.getElementById('next').innerHTML = data
var test = document.getElementsByClassName('gridRow')
//create dict
var new_dict = {}
for(a=0;a<test.length;a++){
if(test[a].children[2].innerText == 'Ready') {
test[a].style.display = 'none';
//drops into the dictionary
put(String(test[a].children[0].innerText).replace(/\n/ig, ''),
test[a].children[3].innerText, new_dict)
}
}
document.getElementById('next').innerHTML = ''
//looping through the dict
for(var index in new_dict) {
document.getElementById('next').innerHTML += ("<br>" + index + " : " +
new_dict[index] + "<br>");
}
the output is the same order the names appear.
Whatever is creating new_dict is creating it incorrectly. It's an array, but the code creating it is using it like a plain object. I'd fix that so that it's, for instance, an array of objects.
But with your current structure:
If you want to loop through its properties in order alphabetically by the property names, you can use Object.keys to get the keys and sort it, then loop through the result via map creating the output:
document.getElementById('next').innerHTML = Object.keys(new_dict)
.sort((a, b) => a.localeCompare(b)) // Sorts lexicographically (loosely, "alphabetically")
.map(key => escapeHTML(key + ": " + new_dict[key]))
.join("<br>"); // Joins them with <br> in-between
}
...where escapeHTML encodes & and <, since you're generating HTML. A quick and dirty version (which is good enough for the above) would be something like:
// ONLY good enough to handle text that isn't in attributes
function escapeHTML(str) {
return str.replace(/&/g, "&").replace(/</g, "<");
}
Based on the way your array seems to be populated, and going for the simplist solution: why don't you just normalize the time value such that you have appropriately pre-pended 0s?
" john doe": "00:19:57"
" Guy Faux ": "00:36:40"
" Charles Sheen ": "01:35:37"
This is a dictionary, not an array. It would be more accurate to refer to the names as "keys" and not "indexes". In particular, the dictionary you have here maps names onto times. Anyway, one thing you could do is make a new dictionary that maps the times onto a list of names (as multiple names might have the same time). Then sort that dictionary's keys.
Use the following fix time formats :
function put(key, value, obj) {
obj[key] = value.replace(/(\b\d\b)/g,'0$1');
return obj;
}
then use:
Object.keys(new_dict)
.sort((a, b) => a.localeCompare(b))
.forEach(p=>document.getElementById('next').innerHTML +="<br>" + p + " : " +
new_dict[p] + "<br>");
I have the following code but I know that there must be a more efficient way to get to my end results. I need a comma separated string but when I try to use .toString I know that I'm not using it in the right place. I've included the code that I am currently using
function load_data() {
var response = [
{"email": "a#123.com","pmid": ["a22222", "a444444", "a555555", "a7777777", "a8888888"]},
{"email": "b#123.com", "pmid": ["b22222", "b444444", "b555555", "b7777777", "b8888888"]},
{"email": "c#123.com", "pmid": ["c22222", "c444444", "c555555", "c7777777", "c8888888"]},
{"email": "d#123.com", "pmid": ["d22222", "d444444", "d555555", "d7777777", "d8888888"]}
];
var singleEmail = $.grep(response, function (element, index) {
return element.email == 'a#123.com';
});
var obj = singleEmail[0];
var pmid = obj.pmid;
var pmidList = ''
for (var i = 0; i < pmid.length; i++) {
pmidList += pmid[i] + ',';
}
alert(pmidList);
}
Also is using grep any more efficient than just looping?
Thanks
Using jQuery is never more efficient. JS has many useful methods these days. Check MDN for browser support though.
Find the right element:
// modern
const element = response.find((el) => el.email == 'a#123.com');
// compatible
var element = response.find(function(el) {
return el.email == 'a#123.com';
});
Stringify the array:
const pmidList = element.pmid.join(',');
// or var for compatibility
pmidList won't have a trailing , like your code, but I'm guessing that's good.
References & support:
const vs var
arrow functions
array.find vs array.filter (grep)
I am trying to assemble a certain string out of a JavaScript object and am having some problems.
I created a function that takes the object and should return the string. The initial object looks like so:
var testObject = {
"Topics": ["Other", "New1"],
"Other": ["try this", "this also"]
};
And I would like the string to spit out this:
"Topics~~Other|Topics~~New1|Other~~try this|Other~~this also"
Here is what I have now:
var testObject = {
"Topics": ["Other", "New1"],
"Other": ["try this", "this also"]
};
function transformObjectToString(activeFilters) {
var newString = "";
var checkFilterGroups = function(filterTopic) {
activeFilters[filterTopic].map(function(selectedFilter) {
var tempString = filterTopic + "~~" + selectedFilter + "|";
console.log("check string", tempString);
newString.concat(tempString);
});
}
for (var filterGroup in activeFilters) {
checkFilterGroups(filterGroup);
}
return newString;
}
console.log(transformObjectToString(testObject));
The temp string seems to be formatted correctly when I check the log, but, for whatever reason, it looks like the concat is not working as I assumed it would.
You should be able to just use += as this is just string concatenation. Then, all you must do is strip the last character. Here's a JSFiddle with the change https://jsfiddle.net/tfs98fxv/37/.
You can use .join('|')
var testObject = {
"Topics": ["Other", "New1"],
"Other": ["try this", "this also"]
};
function transformObjectToString(activeFilters) {
var strings = [];
var checkFilterGroups = function(filterTopic) {
activeFilters[filterTopic].map(function(selectedFilter) {
var tempString = filterTopic + "~~" + selectedFilter;
strings.push(tempString);
});
}
for (var filterGroup in activeFilters) {
checkFilterGroups(filterGroup);
}
return strings.join('|');
}
console.log(transformObjectToString(testObject));
newString = newString.concat(tempString);
this works too.
edit: how this works is, at first newString is set to null so null + tempstring at first loop, and then the newSting is set to a value, value + tempString on second loop and so on. finally you have the concatinated string in one variable which you will be returning.
edit:edit:
Also what #jfriend00 said in the comments, ditto
.concat() returns a new string so newString.concat(tempString); is not
accomplishing anything because you don't assign the result back to
newString. Remember, strings in Javascript are immutable so any
modification always creates a new string
I am currently trying to retrieve the corresponding dial_code by using the name which I am obtaining as a variable.
The application uses a map of the world. When the user hovers over a particular country, that country is obtained using 'getRegionName'. This is then used to alter the variable name. How can I use the variable name to retrieve the dial_code that it relates to?
JSON
var dialCodes = [
{"name":"China","dial_code":"+86","code":"CN"},
{"name":"Afghanistan","dial_code":"+93","code":"AF"}
];
The following code runs on mouse hover of a country
var countryName = map.getRegionName(code);
label.html(name + ' (' + code.toString() + ')<br>' + dialCodes[0][countryName].dial_code);
This code doesn't work correctly. The dialCodes[0][countryName].dial_code is the part that is causing the error, but I'm not sure how to correctly refer to the corresponding key/value pair
If you have to support old browsers:
Loop over the entries in the array and compare to the given name:
var dialCode;
for(var i = 0; i < dialCodes.length; i++) {
if(dialCodes[i].name === countryName) {
dialCode = dialCodes[i].dial_code;
break;
}
}
label.html(countryName + ' (' + dialCode + ')');
If you browser support Array.prototype.filter:
dialCodes.filter(function(e) { return e.name === 'China' })[0].dial_code
If you have control over it, I recommend making your object more like a dictionary, for example if you are always looking up by the code (CN or AF) you could avoid looping if you did this:
var dialCodes = {
CN: { "name":"China","dial_code":"+86","code":"CN" },
AF: {"name":"Afghanistan","dial_code":"+93","code":"AF"}
};
var code = dialCodes.CN.dial_code;
Or
var myCode = 'CN'; // for example
var code = dialCodes[myCode].dial_code;
Since it's an array you can use filter to extract the data you need.
function getData(type, val) {
return dialCodes.filter(function (el) {
return el[type] === val;
})[0];
}
getData('code', 'CN').dial_code; // +86