Intermediate Algorithm Scripting: Wherefore aren't I

Tell us what’s happening:

Hey gang, stuck hard and fast on this one and spinning my wheels. I can’t get my head around how to match multiple objects from the source dataset. It looks like it could be done iteratively with multiple loops but I got the impression we were to steer away from doing that after the Functional Programming section.

Can someone look at this code and give me a hint if I am even on the right track…

Cheers

Your code so far


const collection = [
  { 
      first: "alan", 
      middle: "john",
      last: "smith",

  }, 
  { 
      middle: "john",
      last: "smith" 
  }, 
  { 
      first: "bill" 
  },
  {
      first: "don",
      last: "mattingly"
  },
  {
      first: "alan",
      last: "smith"
  }
];

const source = 
  {   
      first: "alan",
      last: "smith" 
  }
  ;


function whatIsInAName(collection, source) {
// What's in a name?
var arr = [];
// Only change code below this line
var sourceKey = Object.keys(source);
var sourceValue = Object.values(source);
console.log("key of source is",sourceKey,"value is",sourceValue);
for(var j = 0; j<sourceKey.length; j++) {
 arr = collection.filter(collectionElement => (collectionElement.hasOwnProperty(sourceKey[j]) && (collectionElement[sourceKey[j]]== sourceValue[j]))
 )}
return arr;     
}

console.log(whatIsInAName(collection,source));

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36.

Challenge: Wherefore art thou

Link to the challenge:
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou

You’ve written some good code here, it’s just not “good” in the sense that it isn’t performing the task you want.

If I were to break what you have into pseudo code:

loop over the key/value pairs in source
  filter for only collection records that have that key/value
  overwrite arr with the result

Do you see the problem? I see a few.

  1. You are overwriting arr with each pass. So, all arr contains is the results for the last pass.
  2. Even if you were pushing/merging each pass onto arr , you’re only checking one of the source key/value pair at a time so it’s going to return records that match any of the key/value pairs, not all . The latter is what you want.

See if you can work it out. Don’t think about JS for a second and just think about how you would do this. Imagine you had a helper that was perfect at following instructions but had no intuitive of fuzzy reasoning (basically a computer). Imagine those records are on index cards and he can only look at one at a time. How would you tell him to go through them and find what you need. See if you can write it out in pseudo code. Algorithms are more about understanding the pseudocode than the language. I used to go to meetups all the time where we did algorithm challenges and it wasn’t common for three of us to discuss an algorithm solution even though one of us was doing it in JS, one in Java, and one in Python. It didn’t matter.

Give it a shot. If you get stuck, come back and ask again.

It looks like it could be done iteratively with multiple loops but I got the impression we were to steer away from doing that after the Functional Programming section.

But remember that filter is an iterative solution hidden in a prototype method. If it helps to do it using for loops, then do it. Then if you can, try it with prototype methods. Sometimes in solving programming problems you need to take baby steps. As you get better, you can skip over some of those steps, but there will always be a problem you need to break down and test out as you go. This is an important skill. When I did algorithm challenges for interviews, usually I tried to get a solution to work, any solution. Then I’d say, “OK, I think I can make this more efficient”. Or succinct, or clearer, or whatever.

1 Like

See if you can write it out in pseudo code.

This is so good, thank you. That’s how I was doing many of the challenges up to the Functional section where I dropped the ball there for some reason to go straight to coding. I’m going back to writing it out first again! Such a positive, helpful post, thank you. :+1:

Your advice helped me solve it (albeit clunkily no doubt). Now I’m going to try and make it cleaner or more efficient as I don’t like my solution (spoiler blurred below) at all!

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  var flag = false;
  var sourceKey = Object.keys(source);
  var sourceValue = Object.values(source);
  collection.forEach(function(collectionElement) {
      for(var j = 0; j<sourceKey.length; j++) {
          if((collectionElement.hasOwnProperty(sourceKey[j])) && (collectionElement[sourceKey[j]]== sourceValue[j])) {
                flag = true;
              }
              else {
                    flag = false;
                    break;
              }
        }
        if (flag == true) {
            arr.push(collectionElement);
            flag = false;
        }
  })
  return arr;     
}
whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });

Yup, looks good.

If you want, you could probably replace that outer loop with a filter. Anytime you are creating an empty array, looping through something (either with a for loop or a forEach), and selectively pushing things onto that array - that is usually a good spot for filter. (If the pushing were not selective, it would be a good place for a map.) Then your callback could be it’s own function, called by filter - a very FP way to do it. But don’t feel like you have to change it - I just mention it because you mentioned functional programming.

And if I were to be a jerk and critique something…

Things like if (flag == true) are redundant, if (flag) does the same thing.

1 Like

This is perfect, thanks. I was trying to write down the differences between map, filter, and reduce to know when to use which. This helps!

No worries, I’ll remember it now, hah!

Yeah, to put it bluntly, map goes over an array and creates a new array with each element corresponding to an element in the first array. filter selects certain members of an array. reduce takes an array and “reduces” it to a single value. At least that’s how reduce normally works. But if you want to get fancy, you could actually duplicate the effects of map and filter by having that returned value be an array. Actually, I think you can duplicate most of those prototype methods with reduce - not that it’s a good idea in the real world.

And anytime I encounter someone confused by these methods, I always tell them to just write their own. They’re not as difficult as you think, and it really cements what they’re doing.

1 Like