Home > database >  How can I create an array of objects based on some of another array object's properties?
How can I create an array of objects based on some of another array object's properties?

Time:10-06

This this data:

const cocktail = [
    {
        "idDrink":"13070",
        "strDrink":"Fahrenheit 5000",
        "strGlass":"Shot glass",
        "strInstructions":"Cover bottom of shot gla",
        "strIngredient1":"Firewater",
        "strIngredient2":"Absolut Peppar",
        "strIngredient3":"Tabasco sauce",
        "strIngredient4":null,
        "strMeasure1":"1/2 oz ",
        "strMeasure2":"1/2 oz ",
        "strMeasure3":"1 dash ",
        "strMeasure4":null
    }
]

it's my hope to return an array of objects that populate the non-null values of each strMeasure[n] and strIngredient[n]:

[
    {
        strMeasure1: value,
        strIngredient1: value
    },
    {
        strMeasure2: value,
        strIngredient2: value
    },
    …
]

from cocktail array above, the ideal output would be:

[
    {
        measure: '1/2 oz',
        name: 'Firewater'
    },
    {
        measure: '1/2 oz',
        name: 'Absolut Peppar'
    },
    {
        measure: '1 dash',
        name: 'Tobasco sauce'
    },
]

CodePudding user response:

This should do it

Use:

  • Object.entries(cocktail[0]) to get an array of [key, value] from the data
  • filter to get the Ingredients and Measures - and ignore the ones with null values
  • reduce to build up the resulting array

Like this:

const cocktail = [
    {
        "idDrink":"13070",
        "strDrink":"Fahrenheit 5000",
        "strGlass":"Shot glass",
        "strInstructions":"Cover bottom of shot gla",
        "strIngredient1":"Firewater",
        "strIngredient2":"Absolut Peppar",
        "strIngredient3":"Tabasco sauce",
        "strIngredient4":null,
        "strMeasure1":"1/2 oz ",
        "strMeasure2":"1/2 oz ",
        "strMeasure3":"1 dash ",
        "strMeasure4":null
    }
]
const result = Object.entries(cocktail[0])
.filter(([k,v])=>v && k.match(/^str(Ingredient|Measure)\d $/))
.reduce((acc, [k, v]) => {
    const [t, n] = k.match(/^str(Ingredient|Measure)(\d )$/).slice(1);
    acc[n-1] = {...acc[n-1], [t]:v};
    return acc;
}, [])
console.log(result);

You could also do it without the filter step

const result = Object.entries(cocktail[0])
.reduce((acc, [k, v]) => {
    if (v) {
        const [t, n] = k.match(/^str(Ingredient|Measure)(\d )$/)?.slice(1) ?? [] ;
        acc[n-1] = {...acc[n-1], [t]:v};
    }
    return acc;
}, [])
console.log(result);

CodePudding user response:

It looks like you could benefit from using javascripts map() method for parsing out the specific key value pairs from within the object in the array. There are also several ways you could extract the values you want from inside the object such as through dot notation. I have attached a few links here that are very helpful and will give you a much deeper and basic understanding of how to achieve this.

From an array of objects, extract value of a property as array

https://bobbyhadz.com/blog/javascript-convert-array-of-objects-to-array-of-values

https://www.freecodecamp.org/news/javascript-array-of-objects-tutorial-how-to-create-update-and-loop-through-objects-using-js-array-methods/

CodePudding user response:

You can first create an array of object which will have measure and id. Then use the id to get the value from cocktail array

const cocktail = [{
  "idDrink": "13070",
  "strDrink": "Fahrenheit 5000",
  "strGlass": "Shot glass",
  "strInstructions": "Cover bottom of shot gla",
  "strIngredient1": "Firewater",
  "strIngredient2": "Absolut Peppar",
  "strIngredient3": "Tabasco sauce",
  "strIngredient4": null,
  "strMeasure1": "1/2 oz ",
  "strMeasure2": "1/2 oz ",
  "strMeasure3": "1 dash ",
  "strMeasure4": null
}]
const obj = [];
for (let keys in cocktail[0]) {

  if (keys.includes('strIngredient')) {
    const tempObj = {
      measure: cocktail[0][keys],
      id: keys.charAt(keys.length - 1)
    }
    obj.push(tempObj)
  }
}
obj.forEach((elem) => elem.value = cocktail[0][`strMeasure${elem.id}`])
console.log(obj)

CodePudding user response:

Lodash if you don't mind

const cocktail = {"idDrink":"13070","strDrink":"Fahrenheit 5000","strGlass":"Shot glass","strInstructions":"Cover bottom of shot gla","strIngredient1":"Firewater","strIngredient2":"Absolut Peppar","strIngredient3":"Tabasco sauce","strIngredient4":null,"strMeasure1":"1/2 oz ","strMeasure2":"1/2 oz ","strMeasure3":"1 dash ","strMeasure4":null};
    
const parseKey = (str) => [...str.matchAll(/(strIngredient|strMeasure)(\d )/g)].flat();
  
const maping = { strIngredient: 'name', strMeasure: 'measure' };

const iter = (acc, value, key) => {
    const [,  keyName, keyNumber] = parseKey(key);
    if (value && keyName) {
      acc[keyNumber] ??= {};
      acc[keyNumber][maping[keyName]] = value;
    }
    return acc;
};

const result = _(cocktail).transform(iter, {}).values();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

  • Related