简体   繁体   中英

I have a an array of recipe ingredients with different serving amounts, how can I get all possible combinations of these ingredients?

I want to copy recipe with same ingredients, but with varying quantities of each ingredient.

Here is my ingredients object:

const ingredientsToStretch2 = [
  {
    productName: "Strawberries, raw",
    amount: 350,
    numberOfServings: 350,
    servingQuantity: 1,
    incrementSize: 2,
    maxAmount: 354,
  },
  {
    productName: "Blueberries, raw",
    amount: 100,
    numberOfServings: 100,
    servingQuantity: 1,
    incrementSize: 2,
    maxAmount: 104,
  },
  {
    productName: "Blackberries, raw",
    numberOfServings: 100,
    amount: 100,
    servingQuantity: 1,
    incrementSize: 2,
    maxAmount: 104,
  },
];

incrementSize is the number that I want to increase the amount by, maxAmount is the amount where I want to stop incrementing that ingredient.

So far, I created a loop that puts all single ingredient variations into array:

  const handleStretch = () => {
    let stretchedRecipes = [];
    for (let i = 0; i < ingredientsToStretch.length; i++) {
      let combinations = [];
      const gramIncrementSize = ingredientsToStretch[i].incrementSize;
      const maxGramSize = ingredientsToStretch[i].maxAmount;
      const initialNumberOfServings =
        ingredientsToStretch[i].numberOfServings + gramIncrementSize;

      for (
        let j = initialNumberOfServings;
        j <= maxGramSize;
        j += gramIncrementSize
      ) {
        combinations.push({
          productName: ingredientsToStretch[i].productName,
          numberOfServings: j,
        });
      }
      stretchedRecipes.push(combinations);
    }
  };

This gives me this result:

[
  [
    {
      productName: "Strawberries, raw",
      numberOfServings: 352,
    },
    {
      productName: "Strawberries, raw",
      numberOfServings: 354,
    },
  ],
  [
    {
      productName: "Blueberries, raw",
      numberOfServings: 102,
    },
    {
      productName: "Blueberries, raw",
      numberOfServings: 104,
    },
  ],
  [
    {
      productName: "Blackberries, raw",
      numberOfServings: 102,
    },
    {
      productName: "Blackberries, raw",
      numberOfServings: 104,
    },
  ],
];

Now, how do I create all possible combinations out of this array?

example of copies:

  1. same strawberries, numberOfServings+2 on blueberries , same blackberries
  2. same strawberries, numberOfServings+2 on blueberries , same blackberries
  3. same strawberries, same blueberries , numberOfServings+2 on blackberries
  4. same strawberries, same blueberries , numberOfServings+2 on blackberries

Taking the array you already generated as input ( intermediate ), you can do:

const allCombinations = intermediate.reduce(
  (acc, ingredientVariants) => (
    acc.flatMap(prefix => (
      ingredientVariants.map(v =>  [...prefix, v])
    ))
  ),
  [[]],
)

This is not great performance-wise, as our copies the arrays a lot and creates lots of anonymous functions, but given that your output is exponential anyway, it shouldn't really matter.

We start with table of all combinations of 0 ingredients ( [[]] ), then we have all combinations with 1 ingredient, 2 ingredients, and so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM