0

I have an array of objects that I need to filter. I am wondering if it is possible to modify the object in the filter function. I dont want to use .map then .filter because then it would loop thru the array twice making it take more time and wont scale if there are thousands of items in the list.

const cities = [
  {name: 'Los Angeles', population: 100},
  {name: 'New York', population: 80},
  {name: 'Chicago', population: 120},
  {name: 'Houston', population: 60},
  {name: 'Philadelphia', population: 70}
];

const highPopulation = cities.filter(item => {
  // item.isHighPopulation = true
  return item.population >= 100
});

console.log(highPopulation)

Maybe filter isnt the best solution to this problem. I just dont want multiple unessecary loops if I can do this operation in one loop.

1
  • 2
    Did you time how long it took to map then filter? I did this for 100k items and it took 10ms. For 1k items, it was less than 1ms. Commented Nov 8, 2021 at 19:18

3 Answers 3

1

Using Array#reduce:

const cities = [
  {name: 'Los Angeles', population: 100},
  {name: 'New York', population: 80},
  {name: 'Chicago', population: 120},
  {name: 'Houston', population: 60},
  {name: 'Philadelphia', population: 70}
];

const highPopulation = cities.reduce((items, item) => {
  if(item.population >= 100) items.push({...item, isHighPopulation: true});
  return items;
}, []);

console.log(highPopulation)

Using Array#filter and Array#map:

const cities = [
  {name: 'Los Angeles', population: 100},
  {name: 'New York', population: 80},
  {name: 'Chicago', population: 120},
  {name: 'Houston', population: 60},
  {name: 'Philadelphia', population: 70}
];

const highPopulation = cities
  .filter(({ population }) => population >= 100)
  .map(item => ({...item, isHighPopulation: true}));

console.log(highPopulation)

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

7 Comments

Given that the OP cites performance and scalability as the reason to avoid the filter/map approach, I can't think the reduce approach could possibly be acceptable: it turns the O(n) operation into an O(n²) operation, creating and populating a new, larger array every time it encounters a high-population city.
@StriplingWarrior perhaps it's better to use Array#push here :) both solutions now are O(n)
At that point, you're probably just better off using a for loop. filter/map/reduce should be used for non-mutating operations. Loops should be used for altering things. :-)
I didn't quite get your point, I'm not altering here, I'm creating new objects in a certain condition...
Your reduce lambda creates new objects, but it also uses push to alter the given array. Granted, the array is the one you create right there, so at least you're not messing with external objects. It just sort of breaks the functional paradigm. I really like your filter/map solution, btw.
|
0

I am wondering if it is possible to modify the object in the filter function.

It is possible. The code you've posted would do what you're asking if you uncomment the commented line.

It is also a bad idea. Mutating objects in a transformation method like filter violates the command-query separation principle.

I dont want to use .map then .filter

Hopefully you're not modifying objects in map either: you should be creating new objects instead. Something like .map(item => {...item, isHighPopulation: item.population >= 100}).

because then it would loop thru the array twice making it take more time and wont scale if there are thousands of items in the list.

Have you tested this assumption? In my experience it's rare for something to take an acceptable amount of time to do x operations, but an unacceptable amount of time to do 2x operations. If performance is an issue for you, it's probably better to take a broader look at your algorithms and data models. If not, you should probably not be worrying overmuch about it.

Comments

0

With forEach loop, in one iteration and add items to results only on filter criteria

const cities = [
  { name: "Los Angeles", population: 100 },
  { name: "New York", population: 80 },
  { name: "Chicago", population: 120 },
  { name: "Houston", population: 60 },
  { name: "Philadelphia", population: 70 },
];

const isHigh = ({ population }) => population >= 100;

const highPopulation = (arr, res = []) => {
  arr.forEach(
    (item) => isHigh(item) && res.push({ ...item, isHighPopulation: true })
  );
  return res;
};

console.log(highPopulation(cities));

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.