can someone explain why I am getting undefined in my loop? I am trying to run a loop that lets me know if its true if i've watched something as well as the rating. What am I doing wrong?
var films = [
{
movie: "fast and the furious",
rating: 4,
seen: true
},
{
movie:"13 reasons why",
rating: 5,
seen: true
},
{
movie:"beaty and the beast",
rating: 4,
seen: false
}
];
films.forEach(function(movie){
var result = "You have ";
if(movie.seen) {
result += "watched ";
}
else{
result += "not seen ";
}
result += "\"" + films.movie + "\" - ";
result += films.rating + " stars";
console.log(result);
});
You should access the element, not the array, in your iterator function:
films.forEach(function(movie) {
var result = "You have ";
if (movie.seen) {
result += "watched ";
} else {
result += "not seen ";
}
result += "\"" + movie.movie + "\" - ";
result += movie.rating + " stars";
});
You passing a movie parameter in your function. you should use this for result.
var films = [
{
movie: "fast and the furious",
rating: 4,
seen: true
},
{
movie:"13 reasons why",
rating: 5,
seen: true
},
{
movie:"beaty and the beast",
rating: 4,
seen: false
}
];
films.forEach(function(movie){
var result = "You have ";
if(movie.seen==true) {
result += "watched ";
}else{
result += "not seen ";
}
result += "\"" + movie.movie + "\" - ";
result += movie.rating + " stars";
console.log(result);
});
var films = [
{
movie: "fast and the furious",
rating: 4,
seen: true
},
{
movie:"13 reasons why",
rating: 5,
seen: true
},
{
movie:"beaty and the beast",
rating: 4,
seen: false
}
];
films.forEach(function(film){
var result = "You have ";
if(film.seen) {
result += "watched ";
}
else{
result += "not seen ";
}
result += "\"" + film.movie + "\" - ";
result += film.rating + " stars";
console.log(result);
});
Use some other variable to enter foreach and use same variable to read properties.
Related
I want a message to a prompt to appear asking the user to type in a student name. Javascript would look through the student record, which is in a separate JS file, and then output the student's information in the message variable.
Here is the relevant javascript code:
var students=[
{
name:'Chris',
track:'IOS',
achievements:'100',
points:'1000'
},
{
name:'John',
track:'Web Design',
achievements:'90',
points:'1000'
},
{
name:'Brent',
track:'Front-End',
achievements:'70',
points:'1000'
},
{
name:'Josh',
track:'Full-Stack',
achievements:80,
points:'1000'
},
{
name:'Nick',
track:'AI',
achievements:'60',
points:'1000'
}
];
function print(message) {
document.write(message);
}
var message="";
var flag=false;
var search=prompt("Type name of student. Type 'quit' to exit.");
while (search!=="quit") {
for (var i=0; i<students.length; i+=1) {
var studentName=students[i].name;
if (studentName===search) {
flag=true;
break;
}
}
if (flag) {
message+="<h1>"+studentName+"</h1>";
message+="<p>"+students[i].track+"</p>";
message+="<p>"+students[i].achievements+"</p>";
message+="<p>"+students[i].points+"</p>";
} else {
alert("That student does not exist. Try again");
search=prompt("Type name of student");
}
}
print(message);
I realize that I am close, however, my one issue that any variable I try to access from within the for loop will be local to that loop only. So how would my if and else conditions work if I can't access local for loop variables in my conditionals? I simply want it to find a match, once it does, stop the for loop and then proceed to use that specific element index.
I would drop the loop and use find() instead. This will return the found student object, or it will return undefined if the student was not found.
let student = students.find(s => s.name == search)
We can then put the code within a recursive function which will keep calling itself until the user finds a student or enters quit:
var students = [{
name: 'Chris',
track: 'IOS',
achievements: '100',
points: '1000'
},
{
name: 'John',
track: 'Web Design',
achievements: '90',
points: '1000'
},
{
name: 'Brent',
track: 'Front-End',
achievements: '70',
points: '1000'
},
{
name: 'Josh',
track: 'Full-Stack',
achievements: 80,
points: '1000'
},
{
name: 'Nick',
track: 'AI',
achievements: '60',
points: '1000'
}
];
function findStudent() {
let search = prompt("Type name of student. Type 'quit' to exit.");
// Exit the function if the user types 'quit'
if (search == 'quit') return
// Find the student
let student = students.find(s => s.name == search)
let message = "";
// If the student was found, write to the document
if (student) {
message += "<h1>" + student.name + "</h1>";
message += "<p>Track: " + student.track + "</p>";
message += "<p>Achievements: " + student.achievements + "</p>";
message += "<p>Points: " + student.points + "</p>";
document.body.innerHTML = message
}
// The student was not found
// Let the user know and call the function again
else {
alert("That student does not exist. Try again");
findStudent()
}
}
findStudent()
How about this?
var students = [...];
function format(student) {
return (
'<h1>' + student.name + '</h1>' +
'<p>' + student.track + '</p>' +
'<p>' + student.achievements + '</p>' +
'<p>' + student.points + '</p>'
);
}
function lookup(name) {
return students.find(function(student) {
return name === student.name
});
}
function print(message) {
document.write(message);
}
function searchPrompt() {
return prompt("Type name of student. Type 'quit' to exit.");
}
function run() {
var search = searchPrompt();
if (search === 'quit') {
return;
}
var student = lookup(search);
if (student) {
print(format(student));
} else {
alert("That student does not exist. Try again");
run();
}
}
run();
I have an array of files in Javascript. How can I create a string with their names and sizes?
Example:
[ {File1} {File2} ] => "File: my_file1 size: size1 bytes, "File: my_file2 size: size2 bytes".
Not using for - I want to use functions :)
If use for it could be something like this
function createStringForFileArray(arr){
let result = "";
for (let i = 0; i <arr.length; i++ ){
result+= "File"+arr[i].name+" size "+arr[i].size+" ";
}
return result;
}
Iterate using Array#map and create a string for each file, then join all the strings:
const files = [{ name: 'file1', size: 1111 }, { name: 'file2', size: 2222 }];
const result = files.map(({ name, size }) => `File: ${name} size: ${size} bytes`).join(', ');
console.log(result);
You can simply use Array.prototype.reduce() to return a unique string from all your array elements.
Your code would be like this:
function createStringForFileArray(arr) {
return arr.reduce(function(a, b, i){
return a + "File: " + b.name + " size: " + b.size + (i !== array.length - 1 ? ", " : "");
}, "");
}
Demo:
This is a working Demo:
var array = [{
name: "file1",
size: "500Mb"
},
{
name: "Test",
size: "0Kb"
}, {
name: "TAnother File",
size: "30Kb"
}
];
function createStringForFileArray(arr) {
return arr.reduce(function(a, b, i){
return a + "File: " + b.name + " size: " + b.size + (i !== array.length - 1 ? ", " : "");
}, "");
}
console.log(createStringForFileArray(array));
Or you can use .map() function like this:
function createStringForFileArray(arr) {
return array.map(function(f) {
return "File: " + f.name + " size:" + f.size;
}).join(", ");
}
You could try map with reduce:
let str = files
.map(f => "File: " + f.name + " size: " + f.size)
.reduce((prev, curr) => prev + ", " + curr);
Edit: You can do it with just reduce. The original solution by #chsdk did this and was posted before mine, but it had an error (now corrected). So you may want to accept that answer instead.
let str = files.reduce((prev, curr, index, arr) => {
return prev + "File: " + curr.name + " size: " + curr.size + (index === arr.length - 1 ? "" : ", ");
}, "");
I have a simple program that stores student objects in an array and then print the students info to the webpage. I have a print method in my program which takes a parameter and access the div element and then sets elements inner html to the parameter passed to print the message. Please consider the code snippet to see where the document.write method working fine but not the print method.
var student;
var message = "";
var students =
[
{
name: "Alice",
track: "IOS",
achievements: "Bronze",
points: 20400
},
{
name: "Linda",
track: "Front End Development",
achievements: "Silver",
points: 26000
}
];
function print( msg )
{
var output = document.getElementById("output");
output.innerHTML = msg;
}
for( var i = 0; i < students.length; i++)
{
student = students[i];
message = "<h2> Student : " + student.name + "</h2>";
message += "<p> Track : " + student.track + "</p>";
message += "<p> Achievements : " + student.achievements + "</p>";
message += "<p> points : " + student.points + "</p>";
// print(message);
document.write(message);
}
<div id="output">
</div>
It's because your print method replaces the entire output div. So each iteration of the loop overwrites the previous ones output.
You can change:
output.innerHTML = msg;
to:
output.innerHTML += msg;
and it will work correctly.
It works just fine you just need to respect the text currently in the div.
I added a += to the innerHtml call to append the new text
var student;
var message = "";
var students =
[
{
name: "Alice",
track: "IOS",
achievements: "Bronze",
points: 20400
},
{
name: "Linda",
track: "Front End Development",
achievements: "Silver",
points: 26000
}
];
function print( msg )
{
var output = document.getElementById("output");
output.innerHTML += msg;
}
for( var i = 0; i < students.length; i++)
{
student = students[i];
message = "<h2> Student : " + student.name + "</h2>";
message += "<p> Track : " + student.track + "</p>";
message += "<p> Achievements : " + student.achievements + "</p>";
message += "<p> points : " + student.points + "</p>";
print(message);
// document.write(message);
}
<div id="output">
</div>
In this case, your print method is substituting the innerHTML of output each time you call it.
Therefore, if you call print inside a loop, the only displayed result will be the last item on the loop.
If you add a + to the method, you will get what you want. You will need a method to clear the div later on, though.
var student;
var message = "";
var students = [{
name: "Alice",
track: "IOS",
achievements: "Bronze",
points: 20400
},
{
name: "Linda",
track: "Front End Development",
achievements: "Silver",
points: 26000
}
];
function print(msg) {
var output = document.getElementById("output");
output.innerHTML += msg;
}
for (var i = 0; i < students.length; i++) {
student = students[i];
message = "<h2> Student : " + student.name + "</h2>";
message += "<p> Track : " + student.track + "</p>";
message += "<p> Achievements : " + student.achievements + "</p>";
message += "<p> points : " + student.points + "</p>";
print(message);
}
<div id="output">
</div>
I'm having trouble understanding the condition in the else if statement under the for loop in my code. I'd really appreciate it if you could help.
This is an array of objects containing student information, name, study track, achievements, points. I just need help understanding this condition: i === (students.length) -1
var students = [
{ name: 'Dave', track: 'Front End Development', achievements: 158, points: 14730 },
{ name: 'Jody', track: 'iOS Development with Swift', achievements: 175, points: 16375 },
{ name: 'Jordan', track: 'PHP Development', achievements: 55, points: 2025 },
{ name: 'Jody', track: 'Learn WordPress', achievements: 40, points: 1950 },
{ name: 'Trish', track: 'Rails Development', achievements: 5, points: 350 }
];
var htmlMessage = '';
var student;
var search;
var notFound = [];
function print(message) {
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = message;
}
function getStudentReport( student ) {
var report = '<h2>Student: ' + student.name + '</h2>';
report += '<p>Track: ' + student.track + '</p>';
report += '<p>Points: ' + student.points + '</p>';
report += '<p>Achievements: ' + student.achievements + '</p>';
return report;
}
while (true) {
search = prompt('Search student records:\ntype a name Ex: Jody\n(or type "quit" to end)');
if (search === '') {
alert('Please enter a name to initiate search.')
} else if (search === null || search.toLowerCase() === 'quit') {
print('<h2>Thanks for using our student record search services.</h2><p>These names were not found : ' +
notFound.join(', ') + '</p>');
break;
}
for (var i = 0; i < students.length; i++) {
student = students[i];
if (student.name.toLowerCase() === search.toLowerCase()) {
htmlMessage = getStudentReport(student);
print(htmlMessage);
break;
} else if (i === (students.length) -1){
print('<p>' + search + ' was not found.</p>');
notFound.push(search);
break;
}
}
}
The else if is checking for the end of the loop and considering the search failed:
//if you are at the end of the array (searched through all students)
else if (i === (students.length) -1){
//alert user that their search was not found
print('<p>' + search + ' was not found.</p>');
//push the failed search term into an array
notFound.push(search);
//break out of the loop, necessary because of the way the loop is
//written (while(true)) will go forever if not broken
break;
}
...it is -1 because an arrays first item starts at 0 while the length starts counting at 1 ;-)
So there is a difference oft -1.
EDITED:
I'm (still) having a little trouble getting values from a nested array in JSON and appending them to generated html.
I'm currently using the following JSON (updated):
{
"OuterArray": [
{
"memberId": "01",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "02",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "03",
"key01": "",
"included": "false",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "04",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
}
]
}
And this js:
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// etc.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i];
for (var j=0; j<outerArray.length; j++) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[j].keyA + "</p>";
}
}
Note that one of the keys in the outer array has a boolean value which determines whether or not it (the outer array member) is - and its nested array stuff are - included in the page.
So just to reiterate, the goal is:
<div class="outer-array-stuff">
<!-- <snip: some outer array key/values here /> -->
<div class="nested-array-stuff">
<div class="nested-array-stuff">
<p>[e.g., nested array key 1 value]</p>
<p>[e.g., nested array key 2 value]</p>
<p>[etc.]</p>
</div>
</div>
If all the outer array members 'included' are 'true', everything outer & nested loads, but this is not exactly what I want; I need to filter so that only those 'included' !== "false". So now my problem is that despite being inside the if 'included'/else loop, the outer array members stop loading at the first excluded outer array member (actually, the next 'true' outer array member does load, but its nested array stuff doesn't, and then nothing further loads, the entire outer array loop dies.
Any insight as to why this is happening?
Many thanks to dreyescat for the help to this point.
P.S. generally I'm trying to minimize my reliance on jQuery.
Many thanks, svs
You are almost there. Here is your code revised with some comments.
// Generally is not a good practice iterate arrays using for..in
//for (var i in outerArray) {
for (var i = 0; i < outerArray.length; i++) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// This should by outerArray array and not jsonData object.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
// getElementsByClassName gets a list of elements that have that class.
// I suppose you want to add the elements to the corresponding outer array.
// Let's use the loop index i to get the proper parent element. You could also
// just get the last one.
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i]; // help?
// Again I recommend you not to use for..in for arrays.
for (var obj in nestedArray) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
}
See demo.
You could also build the entire nested array stuff before adding it to the div element. Then you don't need to query the document to get the nested array stuff element.
for (var i in outerArray) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
var nestedArray = outerArray[i]["nestedArray"];
var nestedArrayStuff = '<div class=\"nested-array-stuff\">';
for (var obj in nestedArray) {
nestedArrayStuff += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
nestedArrayStuff += '</div>';
myDiv.innerHTML += "<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ nestedArrayStuff
+ "</div>"
+ "</div>";
}
See demo
nestedArray is not a string. your nestedArray array loop should be as follows.
var nestedArray = outerArray[i].nestedArray;
for (var j in nestedArray) {
console.log(nestedArray[j].keyA);
console.log(nestedArray[j].keyB);
}
Here is your complete solution, I used lists to output content. It assumes we have one container:
<div id="mydiv"></div>
Than JS would be:
var myDiv = document.getElementById('mydiv');
var outerArray = [
{
"memberId":"01",
"key01":"",
"key02":"key02 exists, ...",
"included":"true",
"nestedArray":[
{
"keyA":"1",
"keyB":"2"
},
{
"keyA":"3",
"keyB":"4"
}
]
},
{
"memberId":"02",
"key01":"key01 value..",
"included":"true",
"nestedArray":[
{
"keyA":"5",
"keyB":""
},
{
"keyA":"",
"keyB":"8"
}
]
},
{
"memberId":"03",
"key02":"",
"included":"false",
"nestedArray":[
{
"keyA":"",
"keyB":"9"
},
{
"keyA":"",
"keyB":""
}
]
},
{
"memberId":"04",
"key01":"value of key01",
"key02":"key02 value ...",
"included":"true",
"nestedArray":[
{
"keyA":"",
"keyB":"10"
},
{
"keyA":"11",
"keyB":"12"
}
]
}
];
var insertHtml = '';
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
insertHtml += "<ul class=\"outer-array-stuff\">";
insertHtml += " <li>";
insertHtml += " <p class=\"memberId\">memberId(" + i + "): " + outerArray[i].memberId + "</p>"
insertHtml += " <p class=\"key01\">key01: " + ( ( typeof outerArray[i].key01!='undefined' && outerArray[i].key01 ) ? outerArray[i].key01 : '') + "</p>"
insertHtml += " <p class=\"key02\">key02: " + ( ( typeof outerArray[i].key02!='undefined' && outerArray[i].key02 ) ? outerArray[i].key02 : '') + "</p>"
var nestedArray = outerArray[i]["nestedArray"];
if ( nestedArray.length>0 ) {
insertHtml += " <ul class=\"nested-array-stuff\">"
for (var j=0; j<nestedArray.length; j++) {
insertHtml += "<li class=\"keyA\">keyA(" + j + "): " + nestedArray[j].keyA + "</li>";
insertHtml += "<li class=\"keyB\">keyB(" + j + "): " + nestedArray[j].keyB + "</li>";
};
insertHtml += " </ul>"
};
insertHtml += " </li>";
insertHtml += "</ul>"
}
}
myDiv.innerHTML = insertHtml;