0

I have an array

[
  {
    "id": 19,
    "name": "rice",
    "food_group": null,
    "created_at": "2022-03-15T02:38:17.911Z",
    "updated_at": "2022-03-15T02:38:17.911Z"
  },
  {
    "id": 20,
    "name": "water",
    "food_group": null,
    "created_at": "2022-03-15T02:38:17.942Z",
    "updated_at": "2022-03-15T02:38:17.942Z"
  },
  {
    "id": 8,
    "recipe_id": 19,
    "ingredient_id": 19,
    "quantity": 1,
    "measurement_unit": "cup",
    "created_at": "2022-03-15T02:38:17.932Z",
    "updated_at": "2022-03-15T02:38:17.932Z"
  },
  {
    "id": 9,
    "recipe_id": 19,
    "ingredient_id": 20,
    "quantity": 23,
    "measurement_unit": "cup",
    "created_at": "2022-03-15T02:38:17.945Z",
    "updated_at": "2022-03-15T02:38:17.945Z"
  }
]

And I want to reduce these objects down to two objects that represent the ingredient and measurements, making it displayable. Since the ingredient_id is available in the measurement/quantity object I believe this is doable, but I am struggling to see how to do this.

I have a sandbox here where I've been trying

So ideally the array would become

[{"rice": { "measurement_unit": cup, quantity: 1}}...]

Joshua
  • 3,055
  • 3
  • 22
  • 37
Jack Collins
  • 339
  • 1
  • 2
  • 13
  • can't see anything on the code sandbox, but what you seem to have is going to be pretty complicated if you don't have a database lying around, these look like you are going to have to do joins and what not – tsamridh86 Mar 17 '22 at 03:30
  • 1
    Try the link now. Yeah, it's a rails app, and I will be joining and returning it from the server, but wanted to see what was possible in JS – Jack Collins Mar 17 '22 at 03:33
  • then i would suggest waiting for a person who can actually answer this – tsamridh86 Mar 17 '22 at 03:33
  • Is there a reason your array of data isn't in the configuration you already need? I guess you need to `filter` those objects that have names first, and then match the ids to the objects that are left, and build a new array of objects. – Andy Mar 17 '22 at 03:34
  • Please check this link https://stackoverflow.com/questions/40774697/how-can-i-group-an-array-of-objects-by-key – Sukesh Mar 17 '22 at 03:43

2 Answers2

1

While this amount of data manipulation is definitely something better done on the back-end, it is totally do-able in the front-end with JavaScript.

I would manually split the array into the two types, and then create a new array of all the ingredients, but fill in the matching measurement details for each.

// separate the ingredients from the measurements
const ingredientsArr = data.filter(x => x.name);
const measurementsArr = data.filter(x => x.measurement_unit);

// map the ingredients to a new array of objects
const output = ingredientsArr.map(({ id, name }) => {

  // find matching measurement by ingredient id
  const matchingMeasurement = measurementsArr.find(x => x.ingredient_id === id);

  // return object that we want
  return {
    [name]: {
      measurement_unit: matchingMeasurement.measurement_unit,
      quantity: matchingMeasurement.quantity
    }
  }
});
Jacob K
  • 1,096
  • 4
  • 10
1

What you're doing has flaw in case there are multiple recipes with same ingredients in the list, so probably it's better to do the other way around, anyway following is what you asked:

var objs = [{
    "id": 19,
    "name": "rice",
    "food_group": null,
    "created_at": "2022-03-15T02:38:17.911Z",
    "updated_at": "2022-03-15T02:38:17.911Z"
  },
  {
    "id": 20,
    "name": "water",
    "food_group": null,
    "created_at": "2022-03-15T02:38:17.942Z",
    "updated_at": "2022-03-15T02:38:17.942Z"
  },
  {
    "id": 8,
    "recipe_id": 19,
    "ingredient_id": 19,
    "quantity": 1,
    "measurement_unit": "cup",
    "created_at": "2022-03-15T02:38:17.932Z",
    "updated_at": "2022-03-15T02:38:17.932Z"
  },
  {
    "id": 9,
    "recipe_id": 19,
    "ingredient_id": 20,
    "quantity": 23,
    "measurement_unit": "cup",
    "created_at": "2022-03-15T02:38:17.945Z",
    "updated_at": "2022-03-15T02:38:17.945Z"
  }
]

var ingredients = []
var recipes = []

objs.forEach(obj => {
  if ('name' in obj) {
    ingredients.push(obj)
  } else {
    recipes.push(obj)
  }
})

ingredients = ingredients.map(ingredient => {

  match = recipes.find(recipe =>
    recipe.ingredient_id === ingredient.id
  )

  return {
    [ingredient.name]: {
      measurement_unit: match.measurement_unit,
      quantity: match.quantity
    }
  }
})

console.log(ingredients)
BIlguun Zorigt
  • 425
  • 1
  • 9
  • 15