web-dev-qa-db-fra.com

Comparez un tableau d'objets JavaScript pour obtenir Min / Max

J'ai un tableau d'objets et je veux comparer ces objets sur une propriété d'objet spécifique. Voici mon tableau:

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

Je voudrais me concentrer sur le "coût" en particulier et obtenir une valeur minimale et maximale. Je me rends compte que je peux simplement saisir les valeurs de coût et les transférer dans un tableau javascript, puis exécuter le Fast JavaScript Max/Min .

Cependant, y a-t-il un moyen plus simple de faire cela en contournant l’étape du tableau au milieu et en supprimant directement les propriétés de l’objet (dans ce cas, "Coût")?

74
firedrawndagger

Dans ce cas, le moyen le plus rapide consiste à parcourir tous les éléments et à le comparer à la valeur la plus élevée/la plus faible, jusqu'à présent.

(Créer un tableau, invoquer des méthodes de tableau est une opération excessive pour cette opération simple).

 // 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);
47
Rob W

La réduction est bonne pour des choses comme celle-ci: effectuer des opérations d'agrégation (comme min, max, avg, etc.) sur un tableau d'objets et renvoyer un seul résultat:

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

... ou vous pouvez définir cette fonction interne avec la syntaxe de la fonction ES6:

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

Si vous voulez être mignon, vous pouvez attacher ceci à array:

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

Maintenant, vous pouvez juste dire:

myArray.hasMin('ID')  // result:  {"ID": 1, "Cost": 200}
myArray.hasMin('Cost')    // result: {"ID": 3, "Cost": 50}
125
Tristan Reid

Utilisez sort , si vous ne vous souciez pas du tableau en cours de modification.

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

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

Je pense que la réponse de Rob W est vraiment le bon (+1), mais juste pour le plaisir: si vous vouliez être "intelligent", vous pourriez fait quelque chose comme ça:

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"));

ou si vous aviez une structure profondément imbriquée, vous pourriez devenir un peu plus fonctionnel et procéder comme suit:

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; }));

Celles-ci pourraient facilement être classées dans des formes plus utiles/spécifiques.

13
J. Holmes

Utilisez les fonctions Math et extrayez les valeurs de votre choix avec map.

Voici le 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

MISE À JOUR:

Si vous souhaitez utiliser ES6:

var min = Math.min.apply(null, myArray.map(item => item.Cost)),
    max = Math.max.apply(null, myArray.map(item => item.Cost));
11
Rupert

En utilisant Array.prototype.reduce () , vous pouvez intégrer des fonctions de comparaison pour déterminer l'élément min, max, etc. d'un tableau.

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
Mr. Polywhirl

Ceci est une meilleure solution

    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);
2
Deepak Sisodiya

En ajoutant à la réponse de Tristan Reid (+ en utilisant es6), vous pouvez créer une fonction qui accepte un rappel, qui contiendra l'opérateur que vous souhaitez appliquer à prev et 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

Ensuite, vous pouvez simplement l'appeler en utilisant:

const costMin = compare(myArray, 'Cost', (a, b) => a < b);
const costMax = compare(myArray, 'Cost', (a, b) => a > b);
2
James Moran

Ceci peut être réalisé avec les fonctions minBy et maxBy de lodash.

Documentation de Lodash minBy et maxBy

_.minBy(array, [iteratee=_.identity])

_.maxBy(array, [iteratee=_.identity])

Ces méthodes acceptent un iteratee qui est appelé pour chaque élément du tableau afin de générer le critère de classement de la valeur. L'itéré est appelé avec un argument: (valeur).

Solution

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

const minimumCostItem = _.minBy(myArray, "Cost");

console.log("Minimum cost item: ", minimumCostItem);

// Getting the maximum using a functional iteratee
const maximumCostItem = _.maxBy(myArray, function(entry) {
  return entry["Cost"];
});

console.log("Maximum cost item: ", maximumCostItem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
0
Trent