Search code examples
javascriptarraysjavascript-objects

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


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'
    },
]

Solution

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