Code Platoon - Exercise Frustration

Hi there, I’m applying for Code Platoon and I’ve been stuck on one exercise for about a week! I’m really frustrated because to me, my code should be working.

I have a nested object. I need to first access the first keys of the object then the key of the keys object key. The object is as follows:

const customerData = {
  'Joe': { visits: 1 },
  'Carol': { visits: 2 },
  'Howard': { visits: 3 },
  'Carrie': {visits: 4 }
};```

As you can see, the key is a customerName and each customerName has an object with a key of visits and a value of  each customer visit.

Accessing the customerName is very simple. I am using a for in loop like this:

for (var cust in customerData) { … } ```

This works just fine, but then I need to apply some conditions on BOTH the customerName (if it exists or not) and on the number of visits. Evaluating whether the customerName exists is also easy and has not problems. using:

if (customerData[cust] !== custName ) { ... } 
else if (customerData[cust] === custName) { ... }

Accessing the number of visits also works with no problems when the user exists and the number of visits value is already set in the customerData Object by using:

num = customerData[custName].visits;

The problem is that when the customerName doesn’t exist, which means visits also does not exist, the program breaks. Of course, I’m getting a type error because visits is undefined since it does not exist.

I’ve tried a ton of ways to get around this. Some of which were calling num at the end of the first condition where the custName evaluates to false because it does not exist. This seems to work and presents the correct greeting based on my conditions, but I’m still not passing the exercise. It keeps telling me it expects BOTH a welcome it’s your first time greeting and the welcome back greeting immediately following that greeting. So what did I do to solve this problem? I created a label name and continued to beginning of the for loop to make the first condition true after adding the user when the first condition completes.

The problem: This does display what I was told was expected, but now I get an error saying the welcome back and regular customer greetings (condition 2 and 3) instead of what it originally wanted (condition 1 and 2). I still do not pass.

I have NO IDEA what I’m doing wrong here. Can someone please help me? When I remove the label, I pass the first part but not the 2nd. With the label, I fail both parts.
Thanks in advance!!!

Here’s the entire code:

// Write your greetCustomer function here
const customerData = {
  'Joe': { visits: 1 },
  'Carol': { visits: 2 },
  'Howard': { visits: 3 },
  'Carrie': {visits: 4 }
};

function greetCustomer (arr, custName) {
  var greeting = "";
  var num = 0;

  loop:
  for (var cust in customerData) {

      if (customerData.hasOwnProperty(custName) === false) {
        
        console.log(custName, "condition 1");
        greeting = "Welcome! Is this your first time?";
        customerData[custName] = {visits: 1};
        continue loop;
      }
      if (customerData.hasOwnProperty(custName) === true) {
        num = customerData[custName].visits;
         console.log(num);
         if (num === 1) {
          console.log(custName, num, "condition 2");
          greeting = "Welcome back, " + custName + "! We\'re glad you liked us the first time!";
          break;
         }
        else {
          console.log(custName, num, "condition 3");
          greeting = "Welcome back, " + custName + "! It\'s good to see a regular customer.";
        }
      }
    }
    return greeting;
}

greetCustomer(customerData, "Emily");

Hi there! It seems your main issue lies in whether or not if a customer name exists or not. So what you could do, is before you loop through each of your objects. Do an initial check to see if your customer data has that property in it’s own if statement block, and then you can do whatever needs to be done in there, and then return the results, thus skipping over the initial loop, which seems to be causing issues if a property does not exist.

I see that in your loop, you are already checking that, but as a tip, you can check if something is false by adding an “!” before the condition, versus comparing it to ‘false’.

So something like this

if(!customerData.hasOwnProperty(custName)) // Will check if customerData has the user

// To check if the object has a property, you can just leave out the comparison as if it does have that property, it will be true regardless
if(customerData.hasOwnProperty(custName))

I have no idea what the loop thing is, but you can remove that as well.

To shorten the code up even more, since we checked if the object does have an existing name in the beginning of the function. We can actually remove the check for hasOwnProperty in the for loop, as it is guaranteed to exists from the previous check. So all you would need to do is do some if checks on the number of visits.

Thanks for your help. I’ve rewrote the code based on your tips. Here are the question instructions:

“Given the customerData object below, write a function greetCustomer that takes in a similar object and a name. Given that name, return a greeting based on how many times that person has visited your establishment. Essentially, you will check the name given to your function against the names in the object given to your function.”

Now I’m getting undefined for those whose names already exist and neither check passes.

// Write your greetCustomer function here
const customerData = {
  'Joe': { visits: 1 },
  'Carol': { visits: 2 },
  'Howard': { visits: 3 },
  'Carrie': {visits: 4 }
};

function greetCustomer (arr, custName) {
  var greeting = "";

  if (!customerData.hasOwnProperty(custName)) {
      console.log(custName, "condition 1");
      greeting = "Welcome! Is this your first time?";
      customerData[custName] = {visits: 1};
      return greeting;
  }
  else if (customerData.hasOwnProperty(custName)) {
    for (var num in customerData[custName].visits) {
      if (num === 1) {
        console.log(custName, num, "condition 2");
        greeting = "Welcome back, " + custName + "! We\'re glad you liked us the first time!";
        return greeting;
      }
      else {
        console.log(custName, num, "condition 3");
        greeting = "Welcome back, " + custName + "! It\'s good to see a regular customer.";
        return greeting; 
      }
    }
  }
}

greetCustomer(customerData, "Joe");

You’re welcome! You’re pretty close to it, I believe the issue is lying in your loop, you’re getting undefined because you cannot iterate over a single object’s property. Which in this case seems to be visits, you would want to iterate over the entire existing customerData itself. And then within the block of your for in, is where you can check on the number of visits on a particular customer.

So basically have it set up as you did previously, the only crucial thing we only changed here was the check for invalid customer names, as we just moved that out of the for in loop to it’s own if block statement.

for(var cust in customerData) {
      // Check for number of visits in here, then write out your if statements to assign 
         your greeting based on the number of visits.
}

Thanks again. I’ve gone ahead and moved the code back the way I had it and moved the condition check for a nonexistent customer outside of the for loop. The greetings work as expected and I passed the first part of the question. However, I’m still failing the 2nd part and getting this confusing error:

Hmm could be an issue with how the visits are being checked, what does your updated code currently look like?

// Write your greetCustomer function here
const customerData = {
  'Joe': { visits: 1 },
  'Carol': { visits: 2 },
  'Howard': { visits: 3 },
  'Carrie': {visits: 4 }
};

function greetCustomer (arr, custName) {
  var greeting = "";

  if (!customerData.hasOwnProperty(custName)) {
      console.log(custName, "condition 1");
      greeting = "Welcome! Is this your first time?";
      customerData[custName] = {visits: 1};
      return greeting;
  }
  else if (customerData.hasOwnProperty(custName)) {
    for (var cust in customerData) {
      var num = customerData[custName].visits;
      console.log(num);
      
      if (num === 1) {
        console.log(custName, num, "condition 2");
        greeting = "Welcome back, " + custName + "! We\'re glad you liked us the first time!";
        return greeting;
      }
      else {
        console.log(custName, num, "condition 3");
        greeting = "Welcome back, " + custName + "! It\'s good to see a regular customer.";
        return greeting; 
      }
    }
  }
}

greetCustomer(customerData, "Emily");

You should only have 1 return statement, which will be outside of the for in loop, at the very end of the code. But looking at it again, there is no need for the for in loop, it’s actually not doing anything for our purposes, as we’re not even utilizing the key “cust”.

The thing with objects vs an array, is that you can instantly get data from a certain key value pair with bracket notation without ever having to loop through it. In this case, the one critical piece of information that we need is the number of visits from a customer.

Since the first if check handles a non existent user, it would return immediately the greeting, thus not executing any code after that first if block, exiting out of the function completely. So we can get rid of the else if after it, we don’t need to check if the customer exists, as if it does pass the first if check, that customer is guaranteed to be there.

Given as how we can access certain parts of an object without looping, I would also get rid of the entire for in loop as well. All we would really need is a variable for the number of visits, which is ‘num’ in this case. And we can easily assign this, by the exact way you are doing so in the for in loop.

var num = customerData[custName].visits

After we have that variable set up, you would just have your usual if else statement to deal with the greeting message. And then returning that said message, this is the basic skeleton that you can follow:

 var greeting = "";

  if (!customerData.hasOwnProperty(custName)) {
      console.log(custName, "condition 1");
      greeting = "Welcome! Is this your first time?";
      customerData[custName] = {visits: 1};
      return greeting;
  }

 // If you made it past the initial if statement, means that the customer does exist

// Get total number of visits from that customer
var num = customerData[custName] .visits;

// Do your num checks here
if(num === 1) {
  // Assign your greeting variable here if it's equal to 1
} else {
// Do some other stuff
}

Hopefully that helps, and solves the issue!

That makes a lot of sense. I did originally have only one return statement at the end, but then I thought that might be my problem once you recommended returning the value for the first if condition. You’ve explained it very clearly and I appreciate your time and help!!!

I’m going to fix it and let you know if it works.

1 Like

Okay, I’m still at a loss as to why this isn’t working. I have some idea though. I believe what the exercise wants is for the new user to first display a “first time” greeting , add the user to the object, then continue, find the user now exists and then give a Welcome back greeting. This is based on the errors I’m getting. So I tried setting a new variable to newCust = true and setting it to false if the first condition passed and set num to zero if it had not passed. That also did not work so I went back to what I had before tyring that. Then I experimented some more and found that if I use the name ‘Emily’ as the custName part one passes, part two does not and the error is the same as before.

However, if I use the suggested name they provided in the example which is ‘Terrance’ as the custName, both parts fail with the following error:


(other images to follow because I’m a new user and limited to one per post)

Here is their example:

For example:
const customerData = {
 'Joe': {
   visits: 1
 },
 'Carol': {
   visits: 2
 },
 'Howard': {
   visits: 3
 },
 'Carrie': {
   visits: 4
 }
}

// If the customer is not present in customerData:
greetCustomer(customerData, 'Terrance') // 'Welcome! Is this your first time?'

// If the customer has visited only once ('visits' value is 1):
greetCustomer(customerData, 'Joe') // 'Welcome back, Joe! We're glad you liked us the first time!'

// If the customer is a repeat customer: ('visits' value is greater than 1):
greetCustomer(customerData, 'Carol') // 'Welcome back, Carol! It's good to see a regular customer'

Do you have any idea what’s going on here? In the meantime, while I wait for your reply I’m going to sign out of the program and sign back in then clear my cache. Maybe it has to do with that.

Hmm, I have no idea what else could be the issue, without seeing the whole problem. Given what you supplied for their test cases, I went and plugged those in from what I had in my previous post, and came back with the correct results. I have no idea what else the problem is asking for? Maybe post the code sample you have from the revision and go from there.

Also is there a link perhaps to the code challenge?

It’s a repl.it and you have to sign up if you want to see the exercises. Here’s the link and I’m working on Medium-3 Code Platoon exercise.

https://repl.it/student/submissions/11324533

I get all the right responses too, but for some reason the exercise is not passing me on. In case you don’t want to sign up, here is the question:

Instructions from your teacher:

Medium Question #3

Given the customerData object below, write a function greetCustomer that takes in a similar object and a name. Given that name, return a greeting based on how many times that person has visited your establishment. Essentially, you will check the name given to your function against the names in the object given to your function.
For example:

const customerData = {
 'Joe': {
   visits: 1
 },
 'Carol': {
   visits: 2
 },
 'Howard': {
   visits: 3
 },
 'Carrie': {
   visits: 4
 }
}

// If the customer is not present in customerData:
greetCustomer(customerData, 'Terrance') // 'Welcome! Is this your first time?'

// If the customer has visited only once ('visits' value is 1):
greetCustomer(customerData, 'Joe') // 'Welcome back, Joe! We're glad you liked us the first time!'

// If the customer is a repeat customer: ('visits' value is greater than 1):
greetCustomer(customerData, 'Carol') // 'Welcome back, Carol! It's good to see a regular customer'

and here is my code:

// Write your greetCustomer function here
const customerData = {
  'Joe': { visits: 1 },
  'Carol': { visits: 2 },
  'Howard': { visits: 3 },
  'Carrie': {visits: 4 }
};

function greetCustomer (arr, custName) {
  var greeting = "";

  if (!customerData.hasOwnProperty(custName)) {
      console.log(custName, "condition 1");
      greeting = "Welcome! Is this your first time?";
      customerData[custName] = {visits: 1};
      return greeting;
  }
  console.log(customerData);
  var num = customerData[custName].visits;

  if (num === 1) {
    console.log(custName, num, "condition 2");
    greeting = "Welcome back, " + custName + "! We\'re glad you liked us the first time!";
  }
  else {
    console.log(custName, num, "condition 3");
    greeting = "Welcome back, " + custName + "! It\'s good to see a regular customer.";
  }
  return greeting; 
}

console.log(customerData);
greetCustomer(customerData, "Emily");

I’m not sure if it’s wanting us to keep track of visits on a given customer on each test case, if it did then it was worded pretty badly, and would need to increment the visit by one along with sending the message if that’s the case.

Maybe try accessing the customerData object from the function’s arguments rather than grabbing it from outside the function. Instead of customerData, it would be ‘arr’ in your case, since that’s what that first argument is. Although I would recommend changing that name to obj or something since it’s not an array.

But other than that, I have no idea why it’s not working. From the errors it seems like the function is not returning the correct message. Is there any more info underneath the more options? And with those failed tests what were the inputs for the function?

1 Like

This is the gibberish that more info gives:

More info
Error: Expected 'Welcome! Is this your first time?' to contain 'Welcome back, Huralain! It's good to see a regular customer'.
    at https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:267170
    at t (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:267210)
    at e.I [as expectationResultFactory] (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:249867)
    at e.addExpectationResult (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:245068)
    at t.r [as addExpectationResult] (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:249036)
    at t.toContain (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:266537)
    at eval (eval at n.evaluate (https://repl.it/public/replbox_lang/2.3.0/javascript.js:237:152404), <anonymous>:53:53)
    at https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:290616
    at n.run (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:290835)
    at n.execute (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:289470)
    at e.M [as queueRunnerFactory] (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:250740)
    at e.execute (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:245810)
    at e.fn (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:300964)
    at https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:290550
    at n.run (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:290835)
    at e (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:290094)
    at https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:290231
    at https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:288652
    at n [as onComplete] (https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:245437)
    at https://repl.it/public/replbox_lang/2.3.0/javascript.js:684:291024
    at e.exports (https://repl.it/public/replbox_lang/2.3.0/javascript.js:328:67455)
    at m.<computed> (https://repl.it/public/replbox_lang/2.3.0/javascript.js:328:83455)
    at Number.g (https://repl.it/public/replbox_lang/2.3.0/javascript.js:328:83313)
    at MessagePort.b (https://repl.it/public/replbox_lang/2.3.0/javascript.js:328:83335)```


I'll try grabbing obj from the function like you suggested. I did plan on changing that to obj, just got too preoccupied with this frustration of seeming to have it all right, but not being able to pass.

I've tried using the following values: Joe, Carol, Carrie, Emily, Terrance
All return the expected greeting. All but Terrance pass the first test. Terrance fails both.

Again, I really appreciate your help and time!!!

You are amazing!
I just changed all of the customerData to obj and everything worked. That was the only problem. Sometimes it just takes someone else’s eyes or talking through it to get the silly little mistakes : ).

Thanks so much!!!

You’re very welcome! I was in the middle of writing another idea, but glad that’s all it took!

I had a hunch it had to do something with that after looking at the error message. It looked like Hurulain was seen as visited already, which was being modified through the first if block, when you added that new customer in. Which it would be best to not mutate the original data, and just using a reference to it, so it can live in it’s own state in the function.

But this is the best way to learn for sure! Getting past those obstacles, as you learn more from trial and error :slight_smile: Glad that we could both walk through that together. Good luck with everything else!

2 Likes