Is there a shorter way of solving this using higher order functions? Perhaps the filter method?

Viewed 80

Return a new array without the most expensive thing in the list. Your function should preserve the order of the items in this array. The code is correct and so is the output. I don't have a lot of exp with HOF so I would like to see how this can be done using the filter method.

    function removeMostExpensive(list) {
  var expensive = list[0];
  for (var i = 1; i < list.length; i++) {
    if (list[i].price > expensive.price) {
      expensive = list[i];
    }
  }
  var newList = [];
  for (var i = 0; i < list.length; i++) {
    if (list[i] !== expensive) {
          newList.push(list[i]);
    }
  }
  return newList;
}
console.log(removeMostExpensive([
  {
    item: "rice",
    price: 12.75,
    weightInPounds: 20
  },
  {
    item: "chicken",
    price: 6.99,
    weightInPounds: 1.25
  },
  {
    item: "celery",
    price: 3.99,
    weightInPounds: 2
  },
  {
    item: "carrots",
    price: 2.85,
    weightInPounds: 2
  },
  {
    item: "green beans",
    price: 2.55,
    weightInPounds: 2
  }
]));
3 Answers

You can find the most expensive item by mapping the array to the prices and calling Math.max on it. Then filter the array by whether the current item being iterated over has that price:

function removeMostExpensive(list) {
    const max = Math.max(...list.map(obj => obj.price));
    return list.filter(obj => obj.price !== max);
}

That's assuming that your current code works - that if more than one item is tied for the same highest expense, all should be removed.

There won't be much difference with filter but you can do both operation ( finding max & returning the array without max ) on same loop.

Solution without extra memory allocation:

function removeMostExpensive(list) {
  const newList = [];
  let expensive = list[0];

  list.filter((item, index) => {
    if(item.price > expensive.price) {
       expensive = list[index];
    }
    // because the expensive will always change if above condition is true
    if(item !== expensive) {
      newList.push(list[index]);
    }
  });
  return newList;
}

I have only compared your output from the sample input with the above modified version of code. Not sure if this will pass all the test cases but you can simplify your code this way.

You ask for higher functions. You can use a combination of reduce and splice. reduce often comes in powerful, but one needs to wrap the mind around first.

The console.log is only to observe how it works.

function removeMostExpensive(list) {
  var newList = [...list];

  var reducer = function(a, c, i) { 
    console.log(JSON.stringify(a) + ', ' + JSON.stringify(c) + ', ' + i); 
    if (c && c.price > a.price) {
      a.price = c.price;
      a.index = i;
    }  
    return a; 
  }

  var maxInfo = newList.reduce(reducer, {price: -1});
  newList.splice(maxInfo.index, 1);

  return newList;
}

While reduce iterates through the array, it will collect a) the biggest value and b) the index of the particular biggest value. The index is then ready and used for splice.

Related