I’m working on the Profile Lookup challenge and I have some code that fulfills all requirements except for returning “No such contact” when presented with “Bob”, “number”.
When I add a final else statement that I believe should solve this it instead breaks Kristian, Sherlock, and Harry.
Can someone take a look at my code and give me any advice as to what I’m missing here? Am I solving things out of order or is it sheer dumb luck this code works at all?
Thank you for any assistance~!
function lookUpProfile(firstName, prop){
// Only change code below this line
for (var i = 0; i <= contacts.length; i++) {
if (contacts[i].firstName == firstName) {
if(contacts[i][prop]) {
return contacts[i][prop];
} else {
return "No such property";
}
}
/* everything but Bob works until I add this final else
which then breaks Kristian, Sherlock, and Harry */
else {
return "No such contact";
}
}
// Only change code above this line
}
When iterating through all elements in an array with a for-loop, it’s always i < length (not <=; that will exclude the last element).
Think about where return "No such contact" should appear in your code. It should only run after you have iterated through all of your contacts, and are sure there’s no such contact.
Hi @kevcomedia! Thank you so much for replying! Definitely the code that would evaluate and generate the “No such contact” was the issue. As is my MO I was overthinking/overcoding the solution when there was a much more graceful solution possible.
I’m confused by your explanation of comparison operators. It’s the opposite of my understanding of operators with i < length being “less than” and always one less and i <= length being “less than or equal to” which would include the last iteration of length…?
That said, either comparison operator seems to work in the solution I finally hit upon though it seems my .length - 1 must stay either way.
Remember that the index of the last element in an array is always length - 1. If you did i <= length, the loop will try to look for an element beyond the array’s range.
For example if you have ['apple', 'bamboo', 'cashew', 'durian'], which has length 4, its last element has index 3. If you iterated in a for-loop with i <= arr.length, it will loop until i = 4, then try to access index 4 in the array, which does not exist.
Hope this makes sense.
Oh, my bad, scratch this. I meant i will go out of bounds. Sorry for the confusion.
You can create spoilers in the editor. Click the gear icon, then hide details.
Hi, @kevcomedia and thanks again! I see now that the <= was returning “undefined” in my earlier attempts which was another thing driving me batty. Thanks for clearing that up and saving my sanity. ^_^;
Thank you for posting this! I think the <= was preventing my loop from completing, so it never ran the final line in my code. Taking it out made my code work, and I’ve spent hours on this one…
function lookUpProfile(firstName, prop){
for (var i = 0; i < contacts.length; i++){
if (contacts[i].firstName == firstName) {
if (contacts[i].hasOwnProperty(prop) ){
return contacts[i][prop];
} else if (contacts[i].hasOwnProperty(prop) === false){
return “No such property”;
}
// I’ve being looking for this contacts.length - 1, thank you
}else if (i === contacts.length - 1 ){
return “No such contact”;
}
}
Hint: 1
Use a for loop to cycle through the contacts list.
try to solve the problem now
Hint: 2
Use a nested if statement to first check if the firstName matches, and then checks if the prop matches.
try to solve the problem now
Hint: 3
Leave your return “No such contact” out of the for loop as a final catch-all.
try to solve the problem now
Spoiler Alert!!!
function lookUpProfile(firstName, prop){
// Only change code below this line
for (var i = 0; i < contacts.length; i++) {
if (contacts[i].firstName == firstName) {
if(contacts[i].hasOwnProperty(prop)) {
return contacts[i][prop];
}
return "No such property";
}
}
return "No such contact";
// Only change code above this line
}
for (var n = 0; n < contacts.length; n++) {
if (firstName == contacts[n].firstName) {
var x = n;
if (prop === "likes" || prop === "number" || prop === "lastName") {
var value = contacts[x][prop];
return value;
}
else {
return "No such property";
}
}
}
return "No such contact";
But not this?
for (var n = 0; n < contacts.length; n++) {
if (firstName == contacts[n].firstName) {
var x = n;
if (prop === "likes" || prop === "number" || prop === "lastName") {
var value = contacts[x][prop];
return value;
}
else {
return "No such property";
}
}
else {
return "No such contact";
}
}
When the only difference is the else statement being present inside the loop.
I thought every if statement should have an else “closing” statement.
So my question is this:
In what way and why does the else statement interfere with the function??
It’s not requisite that every if statement have an else closing statement; in this case, having the else closing statement inside the loop causes an early return – i.e., the loop will end on its first pass whether or not it can match the firstName property with the first object in the table array (if it does match, it proceeds with the nested if/else for prop; if it doesn’t match, it ends with “no such contact” and checks no further objects).
Putting the “no such contact” return outside the loop instead allows the loop to cycle thru the entire array unless it finds a match for firstName.
It seems like your code is very specific and not much general. Thus your solution would return error if someone added another property and asked about it. No problem here, but would not be scalable
[details=Summary]
function lookUpProfile(firstName, prop){
// Only change code below this line
var result = “”;
/*
Don’t use ‘return’ in the if/else(s), it will stop the for loop looking beyond contacts[0]. E.g. contacts[1] and greater.
Using ‘break’ stops your loop when you found what property you are looking for in the Object or have not found any property whose name is included in ‘prop’.
*/
for(var i = 0; i < contacts.length; i++){
if(contacts[i].firstName === firstName){
if(contacts[i].hasOwnProperty(prop)){
// Make sure you do not do this:
// result = contacts[i].firstName[prop], it’s easy to get confused.
result = contacts[i][prop];
break;
}
else{
result = “No such property”;
break;
}
}
else {
result = “No such contact”;
}
}
return result;
// Only change code above this line
}[/details]
Wow, this has been giving me a lot of trouble, I was sure I hadn’t made any mistakes and I think it was something about writing return contacts[x].prop instead of contacts[x][prop]. I got the impression these were basically interchangeable, the lesson only mentions using brackets when there’s a space in it. What is the effective difference or rule for not using a dot here?
Hi and thanks for providing some great insight. The one thing I don’t understand about arrays is the term used, “length -1”. I know that arrays are indexed based starting from zero, but what does that term mean…a bit confused.