最近遇到一個有關排列組合的計算問題:将多個使用者屬性(性别、地區、級别等)進行排列組合,并篩選出符合條件的使用者群體。除了作為篩選功能外,電商的SKU也可以利用這個算法求出所有的組合情況。
思路
排列組合是組合學最基本的概念。所謂排列,就是指從給定個數的元素中取出指定個數的元素進行排序。組合則是指從給定個數的元素中僅僅取出指定個數的元素,不考慮排序。——百度百科
以上是百度百科關于排列組合的描述,在這個場景中,其實就是把多個屬性的多個元素進行不重複的組合。如:
- 性别:男、女
- 級别:1級、2級、3級
- 地區:廣東、北京
組合出來有12種情況,即各屬性元素個數的乘積:
男 | 女 |
---|---|
男、1級、廣東 | 女、1級、廣東 |
男、2級、廣東 | 女、2級、廣東 |
男、3級、廣東 | 女、3級、廣東 |
男、1級、北京 | 女、1級、北京 |
男、2級、北京 | 女、2級、北京 |
男、3級、北京 | 女、3級、北京 |
使用計算機的解題的思路是:周遊所有屬性,每次将一個屬性的所有元素放入最終結果集中,并将結果集作為模闆,代入下一個屬性計算中。
編碼
function combination(array $options)
{
$rows = [];
foreach ($options as $option => $items) {
if (count($rows) > ) {
// 2、将第一列作為模闆
$clone = $rows;
// 3、置空目前清單,因為隻有第一列的資料,組合是不完整的
$rows = [];
// 4、周遊目前列,追加到模闆中,使模闆中的組合變得完整
foreach ($items as $item) {
$tmp = $clone;
foreach ($tmp as $index => $value) {
$value[$option] = $item;
$tmp[$index] = $value;
}
// 5、将完整的組合拼回原清單中
$rows = array_merge($rows, $tmp);
}
} else {
// 1、先計算出第一列
foreach ($items as $item) {
$rows[][$option] = $item;
}
}
}
return $rows;
}
$options = array(
'sex' => [, ],
'area' => [, , , , , , , , ],
'level' => [, , , ],
);
$rows = combination($options);
原文連結:https://www.lbog.cn/blog/40