2

I have an array of objects which looks like this:

var array = [
   {competitor: "X", fruit: "Cherry", size: 10},
   {competitor: "X", fruit: "Banana", size: 20},
   {competitor: "Y", fruit: "Cherry", size: 5},
   {competitor: "Y", fruit: "Banana", size: 25}
]

How do I get the smallest and unique fruit according to their size regardless of competitor with the result of:

[
   {competitor: "X", fruit: "Banana", size: 20},
   {competitor: "Y", fruit: "Cherry", size: 5}
]
S.K. Jai
  • 35
  • 1
  • 5
  • `How do I get unique and smallest objects in an array` smallest by sorting then unique by filtering – Thomas Aug 23 '17 at 20:34

3 Answers3

6

You can use Array.reduce to create a hash based on fruit name and overwrite if the current item's size is smaller than the stored item's size:

const array = [
   {competitor: "X", fruit: "Cherry", size: 10},
   {competitor: "X", fruit: "Banana", size: 20},
   {competitor: "Y", fruit: "Cherry", size: 5},
   {competitor: "Y", fruit: "Banana", size: 25}
];
const result = array.reduce((p, c) => {
  if (!p[c.fruit] || c.size < p[c.fruit].size) {
    p[c.fruit] = c;
  }
  return p;
}, {});

console.log(result);

// as array
const resultArray = Object.keys(result).map(x => result[x]);

// as an array if Object.values() is available
const resultValues = Object.values(result);

console.log(resultArray)
Rob M.
  • 30,427
  • 6
  • 46
  • 42
  • Thanks! it's working. However, I have trouble with Object.values but solved with this https://stackoverflow.com/questions/38748445/uncaught-typeerror-object-values-is-not-a-function-javascript. – S.K. Jai Aug 23 '17 at 20:48
  • Glad to help out! I suppose `Object.values` is new enough that it's not 100% safe to rely on but glad you found a solution to that :) – Rob M. Aug 23 '17 at 20:49
1
var array = [
   {competitor: "X", fruit: "Cherry", size: 10},
   {competitor: "X", fruit: "Banana", size: 20},
   {competitor: "Y", fruit: "Cherry", size: 5},
   {competitor: "Y", fruit: "Banana", size: 25}
];

var temp = {};
for (var i = 0; i < array.length; i++) {
    var fruit = array[i].fruit;
    var size = array[i].size;
    if (!temp[fruit] || size < temp[fruit].size) {
        temp[fruit] = array[i];
    }
}

var result = [];
for (var key in temp) {
    result.push(temp[key]);
}
console.log(result);
Nix
  • 176
  • 1
  • 10
0

You could use a hash table and a single loop.

var array = [{ competitor: "X", fruit: "Cherry", size: 10 }, { competitor: "X", fruit: "Banana", size: 20 }, { competitor: "Y", fruit: "Cherry", size: 5 }, { competitor: "Y", fruit: "Banana", size: 25 }],
    hash = Object.create(null),
    result = [];
    
array.forEach(function (o) {
    if (!(o.fruit in hash)) {
        hash[o.fruit] = result.push(o) - 1;
        return;
    }
    if (o.size < result[hash[o.fruit]].size) {
        result[hash[o.fruit]] = o;
    }
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324