Profile Lookup problem optimization

Hello World!
I’m a newbie, so please bear with me for this.
I’m really struggling with JS. Things seem to have gone from 0 to 100 pretty fast.
After viewing the video and after reading a few posts about this problem (which I’d never be able to solve this without), I reached this implementation.
It works.
The thing is: can it be more optimized? And why was the for loop necessary to begin with?

// Setup
const contacts = [
  {
    firstName: "Akira",
    lastName: "Laine",
    number: "0543236543",
    likes: ["Pizza", "Coding", "Brownie Points"],
  },
  {
    firstName: "Harry",
    lastName: "Potter",
    number: "0994372684",
    likes: ["Hogwarts", "Magic", "Hagrid"],
  },
  {
    firstName: "Sherlock",
    lastName: "Holmes",
    number: "0487345643",
    likes: ["Intriguing Cases", "Violin"],
  },
  {
    firstName: "Kristian",
    lastName: "Vos",
    number: "unknown",
    likes: ["JavaScript", "Gaming", "Foxes"],
  },
];

function lookUpProfile(name, prop) {
  // Only change code below this line
for (let i = 0; i < contacts.length; i++)
  {
    if (name === contacts[i].firstName)
    {
      if (contacts[i].hasOwnProperty(prop))
      {
        return contacts[i][prop];
      }
      else
      {
        return "No such property";
      }
    }  
  }
  return "No such contact";
  // Only change code above this line
}

lookUpProfile("Akira", "likes");

We have blurred this solution (with [spoiler][/spoiler] tags) so that users who have not completed this challenge can read the discussion in this thread without giving away the solution.

OK, sorry about that. It was my first post. Won’t happen again :slight_smile:

I’m really struggling with JS. Things seem to have gone from 0 to 100 pretty fast.

That’s a very normal feeling - you’re not alone.

The thing is: can it be more optimized?

What do you mean by “optimized”? Do you mean more efficient in terms of processing? I don’t see how. This is an O(n) solution and unless it’s already hashed or sorted or something, you can’t search an array of data any faster, not that I can see.

Do you mean in terms of lines of code? Sure. Not that “fewer lines of code is always better”, but sure, we could tighten it up a bit.

To me, this makes sense:

function lookUpProfile(name, prop) {
  for (let contact of contacts) {
    if (contact.firstName ===  name) {
      return contact[prop] || "No such property";
    }  
  }
  return "No such contact";
}

It’s a little tighter. It does the same exact thing yours does, it’s just a little more effecient with the language. And I think for…of is a better choice, generally, my order of preference for looping is: prototype method => for...of/in => for => while/do-while. You are getting less and less semantically specific.

But again, yours and mine do the exact same things. The first goal is always to solve the problem, which you did.

And why was the for loop necessary to begin with?

How else are you going to search all the items? There are some types of data structures and situations where you can just jump to the correct element. If we said, “get the 3rd element of the array”, then that is easy. But if it’s “find the first/only element that matches this criteria” then that gets harder. How will you find that without starting at the first one and going through them. If I showed you a bookshelf with random books on it without titles showing and said, “find me the only book written by someone named Carol”, you’d have to start with the first one, check the title page, move onto the next, check the title page, etc." It’s just the way the data is (yes/no) organized. You can organized things in different ways. For example, if we knew that the books were organized alphabetically by the author’s first name, and then divided in sections based on the first letter - then that would be a much faster search. But we don’t have that here. We have a bunch of data objects in an unknown order.

2 Likes

Or, I don’t know, maybe this is better:

function lookUpProfile(name, prop) {
  const matchingContact = contacts.find(({ firstName }) => firstName === name)
  if (matchingContact) {
    return matchingContact[prop] || "No such property";
  }  
  return "No such contact";
}

I like that we hide away the details about looping. And less nesting is usually a good thing. But this basically does the same thing, though in a slightly different order.

2 Likes