我就是想不出怎么解决这个问题,在谷歌上彻底搜索了一下也没有结果,我就寄希望于你,希望你能解决这个问题。
给定下面的示例数组:
array(
'Type' => array(
'Toppe',
'Bukser_og_Jeans'
),
'Size' => array(
'Extra_small',
'Small'
),
'Colour' => array(
'Rod'
)
)
(注:这只是一个示例;实际的生活情况可能有更少/更多的组和/或每个组的元素)
我怎样才能得到下面的结果呢?
Toppe,Extra_small,Rod
Toppe,Small,Rod
Bukser_og_Jeans,Extra_small,Rod
Bukser_og_Jeans,Small,Rod
这是一个产品搜索,API只允许从每个查询类型,大小和颜色组的一个"细化"值,但我的任务需要查询和汇总多个API查询的结果。
我认为我需要某种递归函数来完成它,但是我甚至无法生成任何接近我预期结果的代码。
我能在谷歌上找到的都是关于字母甚至字符串的排列,但人们需要例如。"红、蓝、绿"、"蓝、红、绿"、"绿、红、蓝"等等,这显然不是我想要的。
我希望这里有人能理解我想做什么,并有一个想法如何去做。
编辑:@ikegami发布的解决方案,转换为PHP:
$iter = 0;
while (1) {
$num = $iter++;
$pick = array();
foreach ($refinements as $refineGroup => $groupValues) {
$r = $num % count($groupValues);
$num = ($num - $r) / count($groupValues);
$pick[] = $groupValues[$r];
}
if ($num > 0) {
break;
}
print join(', ', $pick)."'n";
}
如果我们有三组物品,每组10件,我们可以使用从0到999的计数器,并将数字分成几位数。
例如,456
% 10 = 6 -------------------------- Item 6 (7th item) in the first group
/ 10 = 45
% 10 = 5 ---------------- Item 5 (6th item) in the second group
/ 10 = 4
% 10 = 4 ------ Item 4 (5th item) in the third group
/ 10 = 0
该算法将一个数转换为以10为基数的数。如果我们想转换成八进制,我们应该用8而不是10。一直使用10(或8),因为每个位置具有相同数量的符号,但如果符号数量因位置而异,该算法也适用。
2
% 2 = 0 ------------------------ Item 0 (1st item) in the first group: Toppe
/ 2 = 1
^ % 2 = 1 --------------- Item 1 (2nd item) in the second group: Small
| / 2 = 0
| ^ % 1 = 0 ------ Item 0 (1st item) in the third group: Rod
| | / 1 = 0
| | ^
| | |
| | +------------ Number of items in third group
| +--------------------- Number of items in second group
+------------------------------ Number of items in first group
这给了我们:
0 = ( 0 * 1 + 0 ) * 2 + 0 = Toppe, Extra_small, Rod
1 = ( 0 * 1 + 0 ) * 2 + 1 = Bukser_og_Jeans, Extra_small, Rod
2 = ( 0 * 1 + 1 ) * 2 + 0 = Toppe, Small, Rod
3 = ( 0 * 1 + 1 ) * 2 + 1 = Bukser_og_Jeans, Small, Rod
下面是一个Perl实现:
my %refinements = (
Type => [
'Toppe',
'Bukser_og_Jeans',
],
Size => [
'Extra_small',
'Small',
],
Colour => [
'Rod',
],
);
my @groups = values(%refinements);
my $iter = 0;
while (1) {
my $num = $iter++;
my @pick;
for my $group (@groups) {
my $r = $num % @$group;
$num = ( $num - $r ) / @$group;
push @pick, $group->[$r];
}
last if $num > 0;
say join(', ', @pick);
}
我知道它不是PHP—我不知道PHP—但你只是问如何解决问题,而不一定是做它的代码,对吗?我希望您能够充分理解上面的Perl代码,从而解决您的问题,并在PHP中重新实现它。
(如果我正在编写Perl解决方案,我会使用算法::Loops的NestedLoops
.)
仅供那些想要PHP翻译的人使用:
function factor_permutations($lists) {
$permutations = array();
$iter = 0;
while (true) {
$num = $iter++;
$pick = array();
foreach ($lists as $l) {
$r = $num % count($l);
$num = ($num - $r) / count($l);
$pick[] = $l[$r];
}
if ($num > 0) break;
$permutations[] = $pick;
}
return $permutations;
}
print_r(factor_permutations(array(array('a', 'b'), array('1', '2', '3'), array('foo', 'bar'))));
for ($i = 0; i < sizeof($Type); $i++) {
for ($j = 0; j < sizeof($Size); $j++) {
for ($k = 0; k < sizeof($Colour); $k++) {
echo $Type[i] . $Size[j] . $Colour[k];
}
}
}
我不够聪明,无法理解ikegami的解决方案,但我能够将其转换为Javascript用于我的目的。我不知道它是如何工作的,但它太棒了!
lists = [["a","b"],["x","y"],["1","2","3"]]
function factorPermutations(lists) {
permutations = []
$iter = 0;
while (1) {
$num = $iter++;
$pick = [];
for (l in lists) {
$r = $num % (lists[l].length );
$num = ($num - $r) / lists[l].length;
$pick.push( lists[l][$r])
}
if ($num > 0) break;
permutations.push( $pick);
}
return permutations
}
console.log(factorPermutations(lists))
是的,我在PHP版本的变量上留下了一些$符号
假设你只有一个嵌套层,你想要的是:
$my_ar[group1][0].(rest_of_the_group_perms[0])
$my_ar[group1][0].(rest_of_the_group_perms[1])
...
$my_ar[group1][N].(rest_of_the_group_perms[K])
也就是说,您可以将问题视为必须连接两个列表/数组。第一个是你的数组的第一个子数组,第二个是(递归的)rest。
所以你需要一个这样的函数:perms($my_arr) {
foreach($elem in $group1) {
$return_list[] = $elem.$rest;
}
}
,其中$group1
是数组的第一个子数组,$group_rest
是剩下的。所以:
perms($my_arr) {
$group1 = head($my_arr);
$group_rest = tail($my_arr);
$rest = perms($group_rest);
$return_list = array();
foreach($elem in $group1) {
$return_list[] = "$elem, $rest";
}
return $return_list;
}
但是$rest
也是一个数组所以你也要循环它:
perms($my_arr) {
$group1 = head($my_arr);
$group_rest = tail($my_arr);
$rest = perms($group_rest);
$return_list = array();
foreach($elem in $group1) {
foreach($relem in $rest) {
$return_list[] = $elem.$relem;
}
}
return $return_list;
}
添加结束条件(null $group_rest
),您将设置:
perms($my_arr) {
$group1 = head($my_arr);
$group_rest = tail($my_arr);
if (length($group_rest) == 0)
$rest = array();
else
$rest = perms($group_rest);
$return_list = array();
foreach($elem in $group1) {
foreach($relem in $rest) {
$return_list[] = $elem.$relem;
}
}
return $return_list;
}