Сравните JavaScript массив объектов, чтобы получить мин / макс - PullRequest
72 голосов
/ 14 января 2012

У меня есть массив объектов, и я хочу сравнить эти объекты по определенному свойству объекта. Вот мой массив:

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

Я бы хотел обратить особое внимание на «стоимость» и получить минимальное и максимальное значение. Я понимаю, что могу просто взять значения затрат и поместить их в массив javascript, а затем запустить Fast JavaScript Max / Min .

Однако есть ли более простой способ сделать это, минуя шаг массива в середине и отключив свойства объектов (в данном случае «Стоимость») напрямую?

Ответы [ 10 ]

124 голосов
/ 06 августа 2015

Снижение хорошо для таких вещей: выполнять агрегатные операции (например, min, max, avg и т. Д.) Над массивом объектов и возвращать единственный результат:

myArray.reduce(function(prev, curr) {
    return prev.Cost < curr.Cost ? prev : curr;
});

..или вы можете определить эту внутреннюю функцию с помощью синтаксиса функции ES6:

(prev, curr) => prev.Cost < curr.Cost ? prev : curr

Если вы хотите быть милым, вы можете прикрепить это к массиву:

Array.prototype.hasMin = function(attrib) {
    return this.reduce(function(prev, curr){ 
        return prev[attrib] < curr[attrib] ? prev : curr; 
    });
 }

Теперь вы можете просто сказать:

myArray.hasMin('ID')  // result:  {"ID": 1, "Cost": 200}
myArray.hasMin('Cost')    // result: {"ID": 3, "Cost": 50}
47 голосов
/ 14 января 2012

Самый быстрый способ, в этом случае, это циклически проходить по всем элементам и сравнивать его с самым высоким / самым низким значением на данный момент.

(Создание массива, вызов методов массива, излишне дляэто простая операция).

 // There's no real number bigger than plus Infinity
var lowest = Number.POSITIVE_INFINITY;
var highest = Number.NEGATIVE_INFINITY;
var tmp;
for (var i=myArray.length-1; i>=0; i--) {
    tmp = myArray[i].Cost;
    if (tmp < lowest) lowest = tmp;
    if (tmp > highest) highest = tmp;
}
console.log(highest, lowest);
21 голосов
/ 14 января 2012

Используйте sort, если вас не волнует изменение массива.

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

var min = myArray[0],
    max = myArray[myArray.length - 1]
13 голосов
/ 14 января 2012

Я думаю Ответ Роба В. действительно правильный (+1), но просто для удовольствия: если вы хотите быть "умным", вы могли бы сделать что-то подобное :

var myArray = 
[
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

function finder(cmp, arr, attr) {
    var val = arr[0][attr];
    for(var i=1;i<arr.length;i++) {
        val = cmp(val, arr[i][attr])
    }
    return val;
}

alert(finder(Math.max, myArray, "Cost"));
alert(finder(Math.min, myArray, "Cost"));

или если бы у вас была глубоко вложенная структура, вы могли бы получить немного больше функциональности и сделать следующее:

var myArray = 
[
    {"ID": 1, "Cost": { "Wholesale":200, Retail: 250 }},
    {"ID": 2, "Cost": { "Wholesale":1000, Retail: 1010 }},
    {"ID": 3, "Cost": { "Wholesale":50, Retail: 300 }},
    {"ID": 4, "Cost": { "Wholesale":500, Retail: 1050 }}
]

function finder(cmp, arr, getter) {
    var val = getter(arr[0]);
    for(var i=1;i<arr.length;i++) {
        val = cmp(val, getter(arr[i]))
    }
    return val;
}

alert(finder(Math.max, myArray, function(x) { return x.Cost.Wholesale; }));
alert(finder(Math.min, myArray, function(x) { return x.Cost.Retail; }));

Их можно легко преобразовать в более полезные / конкретные формы.

11 голосов
/ 30 сентября 2015

Используйте функции Math и извлекайте нужные значения с помощью map.

Вот jsbin:

https://jsbin.com/necosu/1/edit?js,console

var myArray = [{
    "ID": 1,
    "Cost": 200
  }, {
    "ID": 2,
    "Cost": 1000
  }, {
    "ID": 3,
    "Cost": 50
  }, {
    "ID": 4,
    "Cost": 500
  }],

  min = Math.min.apply(null, myArray.map(function(item) {
    return item.Cost;
  })),
  max = Math.max.apply(null, myArray.map(function(item) {
    return item.Cost;
  }));

console.log('min', min);//50
console.log('max', max);//1000

UPDATE:

Если вы хотите использовать ES6:

var min = Math.min.apply(null, myArray.map(item => item.Cost)),
    max = Math.max.apply(null, myArray.map(item => item.Cost));
2 голосов
/ 07 мая 2017

Добавляя к ответу Тристана Рейда (+ используя es6), вы можете создать функцию, которая принимает обратный вызов, который будет содержать оператор, которого вы хотите применить к prev и curr:

const compare = (arr, key, callback) => arr.reduce((prev, curr) =>
    (callback(prev[key], curr[key]) ? prev : curr), {})[key];

    // remove `[key]` to return the whole object

Тогда вы можете просто позвонить, используя:

const costMin = compare(myArray, 'Cost', (a, b) => a < b);
const costMax = compare(myArray, 'Cost', (a, b) => a > b);
2 голосов
/ 16 ноября 2015

Используя Array.prototype.reduce () , вы можете подключить функции компаратора для определения элемента min, max и т. Д. В массиве.

var items = [
  { name : 'Apple',  count : 3  },
  { name : 'Banana', count : 10 },
  { name : 'Orange', count : 2  },
  { name : 'Mango',  count : 8  }
];

function findBy(arr, key, comparatorFn) {
  return arr.reduce(function(prev, curr, index, arr) { 
    return comparatorFn.call(arr, prev[key], curr[key]) ? prev : curr; 
  });
}

function minComp(prev, curr) {
  return prev < curr;
}

function maxComp(prev, curr) {
  return prev > curr;
}

document.body.innerHTML  = 'Min: ' + findBy(items, 'count', minComp).name + '<br />';
document.body.innerHTML += 'Max: ' + findBy(items, 'count', maxComp).name;
2 голосов
/ 05 августа 2015

Это более лучшее решение

    var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
    ]
    var lowestNumber = myArray[0].Cost;
    var highestNumber = myArray[0].Cost;

    myArray.forEach(function (keyValue, index, myArray) {
      if(index > 0) {
        if(keyValue.Cost < lowestNumber){
          lowestNumber = keyValue.Cost;
        }
        if(keyValue.Cost > highestNumber) {
          highestNumber = keyValue.Cost;
        }
      }
    });
    console.log('lowest number' , lowestNumber);
    console.log('highest Number' , highestNumber);
0 голосов
/ 19 июля 2014

Вы можете использовать встроенный объект Array для использования Math.max / Math.min вместо:

var arr = [1,4,2,6,88,22,344];

var max = Math.max.apply(Math, arr);// return 344
var min = Math.min.apply(Math, arr);// return 1
0 голосов
/ 09 января 2014

Еще один, похожий на ответ Кеннебека, но все в одной строке:

maxsort = myArray.slice(0).sort(function (a, b) { return b.ID - a.ID })[0].ID; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...