1

I have an array like this:

var data = [
  { id: 537, name: "aBase" },
  { id: 1, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 8 } },
  { id: 2, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 10 } },
  { id: 3, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 5 } },
  { id: 4, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 2 } },
];

and I want the id of the 'aBase' object and the min y of all of the 'aCourt' objects. The output I want should be something like this:

result = [{id:537,y:2}]

My code so far is like this

let result = [];
data.map((item) => {
    if (item.name === "aBase") {
      if (!result[item.id] === item.id) {
        result[item.id] = item.id;
      }
    } else {
      if (item.name === "aCourt") {
        if (result[item.id] === item.aBaseId) {
          if (!result[item.id].y || result[item.id].y > item.rating.y) {
            result[item.id].y = item.rating.y;
          }
        }
      }
    }
});

How can I fix the code to produce the desired output?

2
  • 1
    both of the things can be separately calculated using forEach , dont complicate it with using other functions like map Commented May 22, 2020 at 20:46
  • 2
    Will the aBase element always be first in data? If so, you can just use result = [{ id: data[0]['id'], y: Math.min(...data.slice(1).map(e => e.rating.y)) }] Commented May 22, 2020 at 21:09

2 Answers 2

2

Array#reduce can do it with a condition to find your base and Math.min to find the lowest e.rating.y:

const data = [
  { id: 537, name: "aBase" },
  { id: 1, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 8 } },
  { id: 2, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 10 } },
  { id: 3, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 5 } },
  { id: 4, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 2 } },
];

const res = data.reduce((a, e) => {
  if (e.name === "aBase") {
    a.id = e.id;
  }
  else {
    a.y = Math.min(a.y, e.rating.y);
  }
  
  return a;
}, {y: Infinity});

console.log(res);

Your expected output wraps this in a single-element array, but this seems unnecessary, so I've omitted it.

Another alternative is using find to collect the base, then map everything else to its y rating, then take the min. The downside is two passes.

const data = [
  { id: 537, name: "aBase" },
  { id: 1, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 8 } },
  { id: 2, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 10 } },
  { id: 3, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 5 } },
  { id: 4, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 2 } },
];

const res = {
  id: data.find(e => e.name === "aBase").id,
  y: Math.min(...data.map(({rating}) => rating ? rating.y : Infinity))
};

console.log(res);

As pointed out in the comments, if you can guarantee aBase as the first element, then you can simplify the above code a bit:

const data = [
  { id: 537, name: "aBase" },
  { id: 1, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 8 } },
  { id: 2, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 10 } },
  { id: 3, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 5 } },
  { id: 4, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 2 } },
];

const res = {
  id: data[0].id,
  y: Math.min(...data.slice(1).map(({rating}) => rating.y))
};

console.log(res);

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

Comments

1

The following should also work for an arbitrary number of elements in your array. It will combine the data of elements with the same id and aBaseIds into a common result object. The order of elements is immaterial.

var data = [
  { id: 123, name: "aBase"},
  { id: 537, name: "aBase" },
  { id: 1, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 8 } },
  { id: 2, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 10 } },
  { id: 3, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 5 } },
  { id: 4, name: "aCourt", aBaseId: 537, rating: { x: 6.4, y: 2 } },
  { id: 5, name: "aCourt", aBaseId: 123, rating: { x: 6.4, y: 17 } },
  { id: 6, name: "aCourt", aBaseId: 123, rating: { x: 6.4, y: 12 } }
];
var res=data.filter(c=>c.name=='aBase')
 .map(c=>({id:c.id, y: Math.min.apply(null,data.filter(e=>e.aBaseId==c.id).map(f=>f.rating.y))}));
console.log(res);

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.