常见规格排列组合问题
在做商城系统中最常见的就是规格,简写pcs。具体来说就是一个商品有多个属性,每个属性有多个规格,这样就形成一些排列组合,做商品库存的时候就要对这些组合进行设定库存和价格。比如,一台电脑内存有16G,32G和64G的,硬盘有500G和1T的,显卡有集成显卡和独立显卡的,这样的商品在售卖的时候选定不同规格价格不一样,仓库备货的库存当然也不一样。
那么对商城后台而言就要单独设定这些产品的价格,就需要把所有的组合排列出来设定价格。
现在我们已知应该产生这样的排列组合然后设定价格和库存(这里面的价格和库存只是为了程序举个例子 并不是实际市场上卖这个价格)
内存硬盘显卡价格库存16G500G集成500010016G500G独立600020016G1T集成700022016G1T独立650012032G500G集成700011032G500G独立750020032G1T集成750030032G1T独立800020064G500G集成750013464G500G独立800034764G1T集成850025864G1T独立900035这里一共是12种组合,那如何用程序生成这样的组合呢?
我们已知从数据库读取能够拿到的属性变量如下:
<?php$spec_list = [ 'memory' => ['16G', '32G', '64G'], 'storage' => ['500G', '1T'], 'graphics' => ['integrated', 'discrete'],];
我们想要的肯定是一个数组,里面有12个元素,每个元素中就是这些规格的组合。
类似于这样的结果
[['16G', '500G', '集成'],['16G', '500G', '独立'],['16G', '1T', '集成'],['16G', '1T', '独立'],['32G', '500G', '集成'],['32G', '500G', '独立'],['32G', '1T', '集成'],['32G', '1T', '独立'],['64G', '500G', '集成'],['64G', '500G', '独立'],['64G', '1T', '集成'],['64G', '1T', '独立'],]
那么怎么实现呢?你要是写三层循环,进行嵌套实现,那也没问题,就是这个属性的个数你得明确的知道有多少种,这样毕竟不是长久之计,而且属性有可能增加或者减少,那将来后台增加了属性,程序该怎么办呢?
还是得自动的计算出来所有组合,不需要手动去检测有多少种属性去foreach遍历。
这里我偷懒的让vscode里面的插件 fitten code 帮我写了一个
<?phpfunction generateCombinations($attributes) { if (count($attributes) === 0) { return [[]]; } $firstAttribute = array_shift($attributes); $combinationsWithoutFirst = generateCombinations($attributes); $combinations = []; foreach ($firstAttribute as $value) { foreach ($combinationsWithoutFirst as $combination) { $combinations[] = array_merge([$value], $combination); } } return $combinations;}
调用一下看看
<?php$spec_list = [ 'memory' => ['16G', '32G', '64G'], 'storage' => ['500G', '1T'], 'graphics' => ['集成', '独立'],];$combinations = generateCombinations($spec_list);var_dump($combinations);
从执行结果来看,是没问题的。
果然是AI改变未来啊,这生成速度比我手动敲的快多了。但是我们也能发现,它用了递归,按道理来说,这种普通的规格属性也不会太多,排列组合几十个已经很多了,再多的话,客户端那边显示就不好看了,而且客户操作起来就不方便,那递归的性能也不会太差。
但是咱们是追求极致的人啊,我再写个循环实现的,避免程序效率太低,看看怎么实现呢?
首先得弄个大循环,在里面一直进行循环,然后还得判断这种组合是否有过,层数如何解决呢?
我想可以先实现二层,再实现多层,逐步增加组合列表,话不多说,看代码
<?phpfunction get_combine_list($spec_list) { if (count($spec_list) <= 1) { return $spec_list; } $result = []; $first_item = array_shift($spec_list); foreach ($first_item as $first_value) { $result[] = [$first_value]; } while ($spec_list) { $tmp_result = []; $second = array_shift($spec_list); foreach ($result as $result_item) { foreach ($second as $second_value) { $tmp_result[] = array_merge($result_item, [$second_value]); } } $result = $tmp_result; } return $result;}
好了,同样的代码调用一下
<?php$spec_list = [ 'memory' => ['16G', '32G', '64G'], 'storage' => ['500G', '1T'], 'graphics' => ['集成', '独立'],];$combinations = get_combine_list($spec_list);
发现结果是一样的,大功告成!
上面递归的思路是递归发现自己是不是最后一个,不是的话就再递归,最终找到最后一个,形成组合,然后再与倒数第二个组合,再与倒数第三个组合。
这里我的思路是,先拿出第一个自然形成结果,再拿出第二个进行组合,然后拿出第三个跟现有结果进行组合,直到拿出最后一个规格进行组合最终形成结果赋值。
方法没有优劣,只有是不是适合以及你自己能不能接受,能不能维护。
页:
[1]