Feedback on problem solution

This is my initial solution to the Drop It problem from Intermediate Algorithms. I know there is probably some magical way this can be achieved more efficiently with reduce() , but I was wondering if the current code is acceptably readable and whether it can be shortened without changing the logic. For instance, there are 2 inner functions inside the two loops that do the same thing, I was wondering if I could declare a single function outside of the loops to be used in both. The main function takes an array as an argument and a function as the second argument, and returns an updated array with values satisfying the second argument, if there is a duplicate value that doesn’t satisfy the function, only the first occurrence is removed, the second one stays in the array.

function dropElements(arr, func) {
    let trueArr = [];
    let final = [];

  for (let n of arr) { // create a loop to populate trueArr with elements satifsying func
    
      function test(b) { // create an inner function to check if an element occurs more than once
    return arr.filter(a => a === b).length
}
      if (func(n) === true || func(n) === false && test(n) > 1) { // if element occurs more than once, push it into trueArr regardless 
          trueArr.push(n)
      } 
  }
  
  for (let i = trueArr.length - 1; i >= 0; i--) { // in order to remove first instance of duplicate instead of last, loop from the end
    
      function test2(b) { // another inner function to check for number of occurences 
    return trueArr.filter(a => a === b).length
}
      if (final.indexOf(trueArr[i]) === -1 || func(trueArr[i]) === true) { 
           final.push(trueArr[i]) // excluding first duplicates (unless the element satisfies func), push all elements into the final array
}
  }
  return final.reverse() // reverse the array to its initial order
}

console.log(dropElements([0, 1, 0, 1], function(n) {return n === 1;}));
console.log(dropElements([1, 2, 3, 4], function(n) {return n >= 3;}));
console.log(dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;}));

HI @Montin !

First off, on congrats on solving it. :slight_smile:
These intermediate algorithms can be tricky to solve.

As to your solution, yes I would say there is a lot going on.
Some of these functions, you can get rid of because they are not being used like this one

When I comment that out, your code still passes.

I do think you can simplify it by getting rid of the multiple loops and inner functions.

The way I chose to solve it was to use one for of loop and a condition inside that checks if func(num) is true return the rest of the array using slice.

function dropElements(arr, func) {
  for (let num of arr) {
    if (func(num)) {
      return arr.slice(arr.indexOf(num))
    }
  }
  return []
}


console.log(dropElements([1, 2, 3, 4], function (n) { return n >= 3; }))

There are dozens of ways to solve this and I am sure other users have solutions they might want to share.

But that was my approach :slight_smile:

Hope that helps!

2 Likes

Ah you’re right, I used the second inner function during one of my failed attempts and then forgot to delete it. Thank you for your feedback.

Yep, I’ve got the same logic just using findIndex() instead of a for loop. @Montin There are so many ways to solve this one! The more you practice these kind of coding challenges, the more you’ll start recognizing the patterns and recall them from memory.

One thing I would definitely say is a bit of a code smell is that you’ve got some filter() calls inside for loops. Since internally filter() is just a special kind of loop, there’s probably some refactoring you can do there.

Here’s my solution:

function dropElements(arr, func) {
  const trueIndex = arr.findIndex(func);
  if (trueIndex < 0) return [];
  return arr.slice(trueIndex);
}
2 Likes

By the way, is return [] here the same as saying else { return [] } ?

If I modified my code like this, it wouldn’t pass

function dropElements(arr, func) {
  for (let num of arr) {
    if (func(num)) {
      return arr.slice(arr.indexOf(num))
    } else {
      return []
    }
  }

}


console.log(dropElements([1, 2, 3, 4], function (n) { return n >= 3; }))

If the condition is false that first iteration of the loop, then it will immediately return an empty array.

But we don’t want that because we need to go through the entire array of numbers and check each number before returning an empty array.

2 Likes

I see thanks. But I just noticed something odd. I tried replicating your code and it seems to be not working for the array I specified, while my function does. I’m sure I’m missing something, could you please clarify this as well? My code Edit fiddle - JSFiddle - Code Playground
Your code
Edit fiddle - JSFiddle - Code Playground

It is working on my end.

The result is

[ 9, 3, 2, 4, 5, 6, 7 ]

because the 9 is the first element in the array where func(num) is true so we are returning the rest of the array starting at 9

1 Like

Omg I completely misunderstood the problem, I thought we had to check all values and remove them accordingly. Thank you.

1 Like

If that were the case then it’d be return arr.filter(func) and done!

But that would get rid of all the false elements, I thought only first occurrences of false elements needed to be removed xD

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.