If you have ever purchased something online, let's say shoes, you probably have selected a particular colour and perhaps a size as well. Easy-peasy - you purchase a variant that you want. But the devs have to create a variant for every single combination of attributes. How to do that?
We will see how to create a function that will generate all possible combinations of attributes. The technique described in this article is called dynamic programming, which you might have heard of if you took a course on algorithms. It is a technique that is used to solve problems by breaking them down into smaller subproblems and solving those subproblems first. I will describe the technique in PHP, but the concept is the same in other languages.
The Problem
Let's take an example of a product on an ecommerce app. Let's say we have the following attributes with their possible values:
- Colour: Red, Green, Blue
- Size: 38, 40, 42
- Style: Slim, Regular, Loose
We want to create a function that will generate all possible combinations of attributes to create a product variant. Maybe we could use loops?
$colors = ['Red', 'Green', 'Blue'];
$sizes = [38, 40, 42];
$styles = ['Slim', 'Regular', 'Loose'];
foreach ($colors as $color) {
foreach ($sizes as $size) {
foreach ($styles as $style) {
echo "Variant: Color=$color, Size=$size, Style=$style\n";
}
}
}
Kinda does the trick, eh? But what if we have to add a new attribute - say, material? We would have to add a new foreach
loop to achieve that.
And what if we do not know how many attributes a product might have? We are not going to ask the user to notify us to add a new loop if they want to add a new attribute. We are going to have to create a function that will generate all possible combinations of attributes without us having to add a new loop.
Recursion to the rescue
The solution to this is to create a recursive function that will generate all possible combinations of attributes. How it works is that it will take the first attribute and generate all possible combinations of the next attribute. It will do this by calling itself with the next attribute. It will continue this until it has generated all possible combinations of all attributes.
Words are probably not going to be the best way to explain this, so let's see how it works in code.
function generateCombinations($attributes, $index = 0, $currentCombination = [], &$allCombinations = []) {
// Base case: if we've processed all attributes, add the current combination to the result
if ($index === count($attributes)) {
$allCombinations[] = $currentCombination;
return;
}
// Recursive case: iterate over each value of the current attribute
foreach ($attributes[$index] as $value) {
// Add the current value to the combination
$currentCombination[$index] = $value;
// Recurse to process the next attribute
generateCombinations($attributes, $index + 1, $currentCombination, $allCombinations);
}
}
// Example usage
$attributes = [
['Red', 'Green', 'Blue'], // Colors
[38, 40, 42], // Sizes
['Slim', 'Regular', 'Loose'] // Styles
];
$allCombinations = [];
generateCombinations($attributes, 0, [], $allCombinations);
// Print all combinations
foreach ($allCombinations as $combination) {
echo "<pre>";
echo "Variant: Color={$combination[0]}, Size={$combination[1]}, Style={$combination[2]}\n";
echo "</pre>";
}
How it works
The function generateCombinations
is a recursive function as it calls itself. The recursive call is made in line 13 in the code snippet above. Here's a breakdown of how it works:
- Function Definition:
generateCombinations($attributes, $index = 0, $currentCombination = [], &$allCombinations = [])
: This function accepts four parameters:$attributes
: An array of arrays, where each sub-array contains possible values for an attribute.$index
: The current index of the attribute being processed. It defaults to 0, indicating the start of the recursion.$currentCombination
: An array that holds the combination of attributes being formed as the recursion progresses.$allCombinations
: A reference to an array where all the generated combinations will be stored.
- Base Case:
- The recursion stops when
$index
equals the number of attributes (count($attributes)
). At this point,$currentCombination
contains a complete set of attribute values, which is then added to$allCombinations
.
- The recursion stops when
- Recursive Case:
- The function iterates over each value of the current attribute (
$attributes[$index]
). For each value:- The value is added to
$currentCombination
at the current$index
. - The function calls itself (
generateCombinations
) with the next attribute index ($index + 1
), passing along the updated$currentCombination
and the reference to$allCombinations
.
- The value is added to
- The function iterates over each value of the current attribute (
Time and Space Complexity
Given that the number of attributes is n
and the number of values for each attribute is m
, the time complexity of this function is O(n^m) and the space complexity is O(n). This is because the function will have to iterate over all possible combinations of attributes and store them in the $allCombinations
array.
Conclusion
This function is a great way to generate all possible combinations of attributes for an ecommerce app. It is a simple and efficient way to create product variants.
Hope this article was helpful. If you have any questions, please feel free to ask. You can reach out to me on X.