Where is "movie" object name coming from in Functional Programming: Use the filter Method to Extract Data from an Array

Hi, I was looking at the solution (#1) for this problem. Where is the object’s name “movie” coming from? I see it referenced nowhere in the provided code. I was using dot notation, and when nothing that I was doing would work, I looked at the solution only to find the “movie” item present. I’m not sure how I could’ve come up with that using the code provided. Could someone please help me understand this? Thank you in advance!

as you have not given a link to the challenge or to the solution you are talking about, it’s difficult to say

but the filtermethod takes a function as argument: a function will have a parameter named in any way you want - is movie maybe the name given to the function parameter?

2 Likes

Oh yes, sorry. Here it is:

And what is the code you are talking about?

Map and filter take a function as a parameter.

That function runs once for each element in the array you are mapping/filtering.

The first parameter of the function is whatever that element is.

Function parameters can be called anything you want; it could be be called “a” or “dbeisfnrbs” or “abracadabra”. But as each element in the array represents a movie, it’s called “movie”

1 Like

Hi Dan, thank you. So it’s clear for me: in the instance of the aforementioned solution code, “movie” isn’t a reference to anything in particular, other than naming a new function for the purpose of the filter? Basically, it boils down to my misunderstanding of syntax, correct?

Okay, I see what you’re saying. I misunderstood the syntax. Thank you!

It’s not naming a new function, it’s because when you write a function, you need to name any parameters.


So as an example of map, what it’s doing:

Say that you have an array of numbers which represent score out of ten:

const scores = [2, 5, 5, 6, 3, 7, 9, 8, 8, 4];

And you want to convert them all to be formatted strings (so like 9 to "9/10"):

for (let i = 0; i < scores.length; i++) {
  scores[i] = `${scores[i]}/10`;
}

That’s fine, it works, but it’s completely imperative and not useful in its own. There has to be a variable called scores, which is an array, then you mutate that etc.

So put it in a function, and make the function take any array of scores, not just that specific one:

function formatScores (scores) {
  let formattedScores = [];

  for (let i = 0; i < scores.length; i++) {
    formattedScores.push(`${scores[i]}/10`);
  }

  return formattedScores;
}

Does this make sense to you at this point? You have a function that takes an array, then you build up a new array by looping over the original one.

So I’ve already written this formatting function twice, and it’s boring, so I’ll put that in a function in its own:

function outOf10 (score) {
  return `${score}/10`;
}

So I could hardcode that:

function formatScores (scores) {
  let formattedScores = [];

  for (let i = 0; i < scores.length; i++) {
    formattedScores.push(outOf10(scores[i]));
  }

  return formattedScores;
}

What if I wanted to convert that score to a star rating? Here’s a function:

function starRating (score) {
  return "⭐".repeat(score);
}

But then the other one is already hardcoded. Ok, so pass the function in as an argument, then you can swap out:

function formatScores (scores, formatFn) {
  let formattedScores = [];

  for (let i = 0; i < scores.length; i++) {
    formattedScores.push(formatFn(scores[i]));
  }

  return formattedScores;
}

So can you see now you have a function that takes an array as the first parameter and a function as the second. It creates a new array by looping over the original array, pushing into the new array the result of running the function on each item.

So now don’t really care what the array or the function are, always works the same:

function map (arr, fn) {
  let result = [];

  for (let i = 0; i < arr.length; i++) {
    result.push(fn(arr[i]));
  }

  return result;
}

So can do

map(scores, outOf10);

That returns

[
  '2/10',
  '5/10',
  '5/10',
  '6/10',
  '3/10',
  '7/10',
  '9/10',
  '8/10',
  '8/10',
  '4/10',
]

Or

map(scores, starRating);

That returns

[ 
  '⭐⭐',
  '⭐⭐⭐⭐⭐',
  '⭐⭐⭐⭐⭐',
  '⭐⭐⭐⭐⭐⭐',
  '⭐⭐⭐',
  '⭐⭐⭐⭐⭐⭐⭐',
  '⭐⭐⭐⭐⭐⭐⭐⭐⭐',
  '⭐⭐⭐⭐⭐⭐⭐⭐',
  '⭐⭐⭐⭐⭐⭐⭐⭐',
  '⭐⭐⭐⭐',
]

Could attach it to the Array prototype, and so this is now the same as the JS builtin function:

Array.prototype.map = function (callback) {
  let result = [];

  for (let i = 0; i < this.length; i++) {
    result.push(callback(this[i]));
  }

  return result;
}

…and can now do scores.map(starRating).

There’s no need to define the callback function separately if it’s only going to be applied once. So can do it inline – so for example to generate the star rating:

scores.map(function starRating (score) {
  return "⭐".repeat(score);
})

The function doesn’t need a name, it can be anonymous:

scores.map(function (score) {
  return "⭐".repeat(score);
});

And arrow functions are built for this kind of situation, so should use that syntax instead:

scores.map((score) => "⭐".repeat(score));

And you are now basically at the same point you were at with the solution to the movie list challenge.

Filter can be described similarly, except the callback has to return true or false:

function filter (arr, callback) {
  let result = [];

  for (let i = 0; i < arr.length; i++) {
    if (callback(arr[i])) {
      result.push(arr[i]);
    }
  }

  return result;
}

Instead of altering the values and pushing them all to the new array, all it does is push to the new array if the function returns true.

Then same can be done to understand all the other array iteration functions that take a function as an argument – for example reduce or every or find or some.

1 Like

Wow, Dan. Thank you for taking time out to explain it like that. It definitely makes more sense to me now. Learning Js has felt a little like drinking from a fire hose at times, but eventually things click into place. I really appreciate the help!

1 Like