1

The exarcise asks me to: "create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument). If no element passes the test, return undefined.", and i wrote this code:

function findElement(arr, func) {
    let array = arr.map(func);

    if (array != null) {
        return array[0];
    }else {
        return [];
    }
}

Can anyone please explain to me why this is not working? For anyone who is wondering, this is the 9th exercise of Basic Algorithm Scripting in freeCodeCamp

5
  • 1
    Do not use higher-order functions like map here. Write a plain loop instead. It's an exercise in basic scripting. Commented Jun 3, 2020 at 9:46
  • First, check arr is an array, second, check function is match with Array.map and return items Commented Jun 3, 2020 at 9:48
  • "why is this is not working?" - array will never be null, it will be an array of true/false values. It might at best be empty if arr was empty. And you should never return an empty array, the task says to return undefined if no element is found. Commented Jun 3, 2020 at 9:49
  • @VươngVũNguyễn Are you trying to describe why the current code does not work, or was that meant as a solution? Commented Jun 3, 2020 at 9:50
  • @Bergi sorry if my comment let you uncomfortable, i just try to get an advice but english not my native language and I have no sharing experience in stackoverflow. Commented Jun 3, 2020 at 10:04

3 Answers 3

2

array is a new array containing the result of calling func on each element of the original array arr.

array != null will always be true because map() returns an array, it doesn't return null. Therefore you will always end up on the return array[0] branch, which returns the first element of this new array instead of the first element of the original array where the condition passes, as the requirements state.


One way of solving your problem would be to loop through the original array (see the for...of statement for how to do that in modern JavaScript), call func on each element, and return the element for which the test passes (the element for which calling func on it results in true).

If nothing was returned by the end of the loop and your function ends up returning nothing, then that is equivalent to it returning undefined, so you don't need to do anything extra for that.

Solution:

function findElement(arr, func) {
    for (const element of arr) {
        if (func(element)) {
            return element;
        }
    }
}

(reveal after you completed your own implementation, or if you get stuck)


Another way would be to use a functionality that already exists in JavaScript, which is the find() function that's defined on all arrays and does exactly what you need. See Michael Mishin's answer about that.

And if you explore all the functions that exist on arrays (look at the left of the page for Array.prototype...), you'll find even more ways of doing this in JavaScript. Consider how you could use any of these functions to solve your problem: filter(), findIndex(), forEach(), indexOf().

Solution using your map() call and indexOf():

function findElement(arr, func) {
    // results is an array containing boolean values (true or false)
    // at the same positions (indexes) as the original values
    // from arr.
    const results = arr.map(func);

    // Try to find the index of the first passed test, which is the
    // first index where the test result is true.
    const firstSuccessIndex = results.indexOf(true);

    // indexOf() returns -1 if it can't find anything
    if (firstSuccessIndex > -1) {
        // If we're here, then indexOf() must have found something,
        // because firstSuccessIndex is greater than -1, so return
        // the element at the index found by indexOf().
        return arr[firstSuccessIndex];
    }

    // If we get here, then it means firstSuccessIndex was not greater
    // than -1, so indexOf() didn't find any passed test result (any
    // value in the results array that is true).

    // In that case, the requirements say that the function should
    // return undefined. Not returning anything is equivalent to
    // returning undefined, so we can end the function here.
}

// A shorter version of the same function could be:

function findElement(arr, func) {
    return arr[arr.map(func).indexOf(true)];
}

// If indexOf() returns -1, then the function will return
// arr[-1], and since there's nothing at index -1 in arr,
// arr[-1] will be undefined, therefore the function will
// return undefined.

(reveal after you completed your own implementation, or if you get stuck)

Sign up to request clarification or add additional context in comments.

Comments

1

arr.map returns the array of elements. arr.find returns the first element found, and if there are no such elements, returns undefined.

function findElement(arr, func) {
    return arr.find(func);
}

5 Comments

Thought of that as well, but the post had some code in it and the question was "Can anyone please explain to me why this is not working?"
I explained: because Array.map always returns an array.
Yep, but that does not answer the question at least to the extend a lerner would get it. rid's answer far better.
If you think a little logically, then this is the answer.
@NiklasE. if you are dissatisfied about the answer, feel free to improve it by editing or post your own answer.
0

Try to break your code down per line and read out loud what it is doing. This is a method called rubber ducking in which you explain to yourself what is happening (or pretending to talk to a rubber duck and explaining your code to it).

Your findElement function takes in two arguments, an array and a function. First you create a new array resulting from the map() method with the func as callback. The map() method will always return an array with the same amount of values as the original array. So unless your array was empty from the start, it will not get the result that you want. Instead use filter(), find() or findIndex() to get the a filtered array, a single item or an index to the item you are looking for.

Next you check if the array does not have a value of null. But based on the result of the map() method it will never be null. Instead you should check if the length property of the array is more than 0. This will indicate if the array is populated or not.

array.length > 0

Then if the array checks out you return the first item in the array. That is the correct approach.

In the else statement, when the array should be empty, you return an empty array. But the assignment asked to return undefined. Return that instead.
And if you only have an if...else statement and return something in both statements, then you don't need an else because the function will stop at either return statements.

So putting all the above together. With the filter() example.

function findElement(arr, func) {
  let filtered = arr.filter(func);
  if (filtered.length > 0) {
    return filtered[0];
  }
  return undefined;
}

With the find() method.

function findElement(arr, func) {
  return arr.find(func);
}

With the findIndex() method.

function findElement(arr, func) {
  let index = arr.findIndex(func);
  if (index > -1) {
    return arr[index];
  }
  return undefined;
}

Or without any higher order functions and a basic for loop.
I would recommend learning the usage of these loops first before handling the array methods, because the internals of those methods work a lot like this. And knowing how it works will give you a greater understanding of what you can do with it and how to use it.

function findElement(arr, func) {
  for (let i = 0; i < arr.length; i++) {
    let current = arr[i];
    if (func(current) === true) {
      return current;
    }
  }
  return undefined;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.