[Vuejs]-How to get least(min) value from array of object?

0👍

You are doing the mapping wrong. You have the condition inside the callback which only gives you one item at a time. Instead, you should filter() the collection to only the type you want first, then get the min() price.

Underscore has the _.chain() method which allows you to do multiple operations on the same dataset without needing to save intermediate results. To get the result at the end, you need to call .value() to signify no further calls would be chained:

const arr = [ { "id":1, "type":"type1", "selling_price":2199, }, { "id":2, "type":"type1", "selling_price":4999, }, { "id":3, "type":"type1", "selling_price":6999, }, { "id":4, "type":"type2", "selling_price":1999, }, { "id":5, "type":"type2", "selling_price":2399, }, { "id":6, "type":"type2", "selling_price":2999, } ];

const result = _.chain(arr)
  .filter(item => item.type === "type1")
  .min('selling_price')
  .value();
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.11.0/underscore-min.js"></script>

If you want just the price, not the object itself, you can use map() to extract just that property:

const arr = [ { "id":1, "type":"type1", "selling_price":2199, }, { "id":2, "type":"type1", "selling_price":4999, }, { "id":3, "type":"type1", "selling_price":6999, }, { "id":4, "type":"type2", "selling_price":1999, }, { "id":5, "type":"type2", "selling_price":2399, }, { "id":6, "type":"type2", "selling_price":2999, } ];

const result = _.chain(arr)
  .filter(item => item.type === "type1")
  .map('selling_price')
  .min()
  .value();
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.11.0/underscore-min.js"></script>

If you want a fallback value in case of an empty array, currently the code will return Infinity, since this is the default return of min. Unfortunately, Underscore doesn’t have a comprehensive enough API to easily solve it. One easy way is to just check for that value and substitute it with another for example.

if (result === Infinity) {
    result = null;
}

An alternative if you want to use only Undescore is to define your own method via mixin(). Many methods might solve the issue here but as a general helper method, I’d go for or() which will allow you to swap a value with another:

/**
 * Generic function that either value or if the value fails a test a fallback
 * @param {*} value - value to be tested or substituted
 * @param {*} otherValue - fallback in case `value` fails the test
 * @param {Function} [test] - what the value would be tested against. By default it fails for null or undefined
 */
_.mixin({
  or: function(value, otherValue, test = x => x != null ) {
    return test(value) ? value : otherValue ;
  }
});

const fullArray = [ { "id":1, "type":"type1", "selling_price":2199, }, { "id":2, "type":"type1", "selling_price":4999, }, { "id":3, "type":"type1", "selling_price":6999, }, { "id":4, "type":"type2", "selling_price":1999, }, { "id":5, "type":"type2", "selling_price":2399, }, { "id":6, "type":"type2", "selling_price":2999, } ];

const emptyArray = [];


function getMinimum(arr) {
  return _.chain(arr)
    .filter(item => item.type === "type1")
    .map('selling_price')
    .min()
    .or("", _.isFinite) //use the or() mixin and pass a different test function that rejects `Infinity`
    .value();
}
  
const fullResult = getMinimum(fullArray);
const emptyResult = getMinimum(emptyArray);

console.log(`fullResult is [${fullResult}]`);
console.log(`emptyResult is [${emptyResult}]`); //empty string
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.11.0/underscore-min.js"></script>

Lastly, if you like Underscore but find the API a bit limiting, like in this case, I’d suggest switching to Lodash. It is very close to Undescore as it splintered off at some point in the past. Lodash has a bit more consistent interface and a lot more functionality, so it a lot of cases it’s a straight upgrade over Underscore or at least on par. The functionality you want expressed in Lodash is this:

const fullArray = [ { "id":1, "type":"type1", "selling_price":2199, }, { "id":2, "type":"type1", "selling_price":4999, }, { "id":3, "type":"type1", "selling_price":6999, }, { "id":4, "type":"type2", "selling_price":1999, }, { "id":5, "type":"type2", "selling_price":2399, }, { "id":6, "type":"type2", "selling_price":2999, } ];

const emptyArray = [];


function getMinimum(arr) {
  return _.chain(arr) //no need for .chain() as Lodash implicitly chains via this
  .filter(item => item.type === "type1")
  .map('selling_price')
  .min() //min defaults to `undefined` if nothing is found
  .defaultTo(''); // similar to the `or()` mixin above but only for `undefined`, `null`, or `NaN`
  .value()
}
  
const fullResult = getMinimum(fullArray);
const emptyResult = getMinimum(emptyArray);

console.log(`fullResult is [${fullResult}]`);
console.log(`emptyResult is [${emptyResult}]`); //empty string
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

Lodash supports everything needed out of the box to complete the entire operation, unlike Underscore.

0👍

You use the function minBy and filter function of lodash

let filter_arr = _.filter(arr, function(o) { return o.type=='type1';})
_.minBy(filter_arr,function(o) { 
  return o.selling_price; 
 });    
 

It will give as below result

{id: 1, selling_price: 2199, type: "type1"}

Hope it will help you

Leave a comment