7

I need to filter this object array by minimum value of 'rest' attribute. This is an one way to do it. Is there any other ways ?

'data' variable is a result of chained function. Is there any other way to do this without calling 'data' variable again inside Math.min() function.

let data = 
[ { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } ]

let result = data.filter(e=> e.rest === Math.min(...data.map(f=>f.rest) ) );
console.log(result);

// result is
//[ { size: 5, qty: 2, rest: 0 },
//  { size: 2, qty: 5, rest: 0 },
//  { size: 1, qty: 10, rest: 0 }]

5 Answers 5

11

The easiest way is to pull the min function out of the filter like this:

let min = Math.min(...data.map(item => item.rest))

This is much more efficient as we are no longer loop over the data to find the min for every iteration of the filter.

We now have n * 2 passes instead of n^2 passes. (n is the size of your data set, 5 in this case)

Full example below:

let data = [ 
  { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } 
]

let min = Math.min(...data.map(item => item.rest))
let result = data.filter(item => item.rest === min)
console.log(result)

Hope this helps!

Lloyd

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

3 Comments

Thank you.yeah I missed that issue. Isn't there any other way to do this with method chaining ?
you will always have to compare the rest values to a minimum variable or pre defined threshold, your initial post is an example of Method chaining.
Thanks anyway. :)
4

data.map inside of data.filter is O(N^2); for an O(N) solution, iterate through data ahead of time to calculate the minimum, then filter by that minimum:

let data = 
[ { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } ];
const minRest = Math.min(...data.map(({ rest }) => rest));

let result = data.filter(({ rest }) => rest === minRest);
console.log(result);

2 Comments

Thanks. I missed that. yet this isn't what I'm looking for. is there any other way without declaring a variable.
Unfortunately no, you'll have to declare or use another variable if you want O(N) performance. (if you don't want to expose it to the outer scope, feel free to put it into an IIFE)
2

imo. the simplest/best solution is the one @CertainPerformance gave you.

Just wanted to add another solution with linear runtime (that truly iterates only once over the Array)

let data = [
  { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } 
];

let result = data.reduce((result, item) => {
  let minRest = result.length? result[0].rest: item.rest;

  if (item.rest < minRest) {
    minRest = item.rest;
    result.length = 0;
  }

  if (item.rest === minRest) {
    result.push(item);
  }

  return result;
}, []);

console.log(result);

@mathieux51 got me another idea how you can do this inside a method chain, but the readability/clarity/intention is not as good as with the other approaches:

let data = [
  { size: 5, qty: 2, rest: 0 },
  { size: 2, qty: 5, rest: 0 },
  { size: 1, qty: 10, rest: 0 },
  { size: 3, qty: 3, rest: 1 },
  { size: 4, qty: 2, rest: 2 } 
];

let result = data.sort((a, b) => a.rest - b.rest)
                 .filter((item, index, array) => item.rest === array[0].rest);

console.log(result);

2 Comments

Thanks a lot. Last one is the one I'm looking for.
Sorting has O(N log N) complexity though
0

It sounds like you want to sort the list. I would do it as following:

const result = data.sort((a, b) => a.rest - b.rest)

2 Comments

sort and filter by minimum rest value.
Just sorting should also work. Get first or last item which would be min and max
0

Get Min or Max Since no one mentioned this method I will update it here.

myArray.sort(function (a, b) {
return a.rest - b.rest
})

var min = myArray[0],
max = myArray[myArray.length - 1]

It has good readability/clarity/intentions.

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.