我有一个关联数组:
$arr = [];
$arr['One'] = 1;
$arr['Two'] = 2;
$arr['Three'] = 3;
$arr['Four'] = 4;
$arr['Five'] = 5;
$arr['Six'] = 6;
我想用它来生成排列对:
$keys = array_keys($arr);
$result = generatePermutations($keys);
其中$result
是一组唯一对的数组:
//as per example, $result =
$result = [[['One','Two'],['Three','Four'],['Five','Six']],
[['One','Three'],['Two','Four'],['Five','Six']],
[['One','Four'],['Two','Three'],['Five','Six']],
[['One','Five'],['Two','Three'],['Four','Six']],
[['One','Two'],['Three','Five'],['Four','Six']],
[['One','Three'],['Two','Five'],['Four','Six']],
[['One','Six'],['Two','Three'],['Four','Five']],
[['One','Two'],['Three','Six'],['Four','Five']],
etc..
];
我发现了多种生成排列的方法,但是大多数方法并没有特别关注对,而且很多方法都将所有排列放在一个数组中。
答案 0 :(得分:2)
迭代它们两次以生成唯一组合,然后遍历组合以形成唯一对:
<?php
$arr = [];
$arr['One'] = 1;
$arr['Two'] = 2;
$arr['Three'] = 3;
$arr['Four'] = 4;
function generatePermutations($array) {
$permutations = [];
$pairs = [];
$i = 0;
foreach ($array as $key => $value) {
foreach ($array as $key2 => $value2) {
if ($key === $key2) continue;
$permutations[] = [$key, $key2];
}
array_shift($array);
}
foreach ($permutations as $key => $value) {
foreach ($permutations as $key2=>$value2) {
if (!in_array($value2[0], $value) && !in_array($value2[1], $value)) {
$pairs[] = [$value, $value2];
}
}
array_shift($permutations);
}
return $pairs;
}
print_r(generatePermutations($arr));
答案 1 :(得分:1)
Class 'JetFlight' must either be declared abstract or implement abstract method 'compareTo(Object)' in 'Flight'
答案 2 :(得分:1)
我打算将此称为“工作解决方案”。我当然可能有冗余过滤器或浪费的迭代,但我现在已经开发和调试了太多时间而且我不再敏锐。如果/当我发现改进此代码块的方法(或某人提出建议)时,我会更新我的答案。
代码:(Demo)
function pairedPerms($arr){
$val1=$arr[0];
$pairs_per_set=sizeof($arr)/2;
foreach($arr as $v1){ // $arr is preserved/static
$arr=array_slice($arr,1); // modify/reduce second foreach's $arr
foreach($arr as $v2){
if($val1==$v1){
$first[]=[$v1,$v2]; // unique pairs as 2-d array containing first element
}else{
$other[]=[$v1,$v2]; // unique pairs as 2-d array not containing first element
}
}
}
for($i=0; $i<$pairs_per_set; ++$i){ // add one new set of pairs per iteration
if($i==0){
foreach($first as $pair){
$perms[]=[$pair]; // establish an array of sets containing just one pair
}
}else{
$expanded_perms=[];
foreach($perms as $set){
$values_in_set=[]; // clear previous data from exclusion array
array_walk_recursive($set,function($v)use(&$values_in_set){$values_in_set[]=$v;}); // exclude pairs containing these values
$candidates=array_filter($other,function($a)use($values_in_set){
return !in_array($a[0],$values_in_set) && !in_array($a[1],$values_in_set);
});
if($i<$pairs_per_set-1){
$candidates=array_slice($candidates,0,sizeof($candidates)/2); // omit duplicate causing candidates
}
foreach($candidates as $cand){
$expanded_perms[]=array_merge($set,[$cand]); // add one set for every new qualifying pair
}
}
$perms=$expanded_perms; // overwrite earlier $perms data with new forked data
}
}
return $perms;
}
//$arr=['One'=>1,'Two'=>2];
//$arr=['One'=>1,'Two'=>2,'Three'=>3,'Four'=>4];
$arr=['One'=>1,'Two'=>2,'Three'=>3,'Four'=>4,'Five'=>5,'Six'=>6];
//$arr=['One'=>1,'Two'=>2,'Three'=>3,'Four'=>4,'Five'=>5,'Six'=>6,'Seven'=>7,'Eight'=>8];
$result=pairedPerms(array_keys($arr));
//var_export($result);
echo "[\n";
foreach($result as $sets){
echo "\t[ ";
foreach($sets as $pairs){
echo "[",implode(',',$pairs),"]";
}
echo " ]\n";
}
echo "]";
输出:
[
[ [One,Two][Three,Four][Five,Six] ]
[ [One,Two][Three,Five][Four,Six] ]
[ [One,Two][Three,Six][Four,Five] ]
[ [One,Three][Two,Four][Five,Six] ]
[ [One,Three][Two,Five][Four,Six] ]
[ [One,Three][Two,Six][Four,Five] ]
[ [One,Four][Two,Three][Five,Six] ]
[ [One,Four][Two,Five][Three,Six] ]
[ [One,Four][Two,Six][Three,Five] ]
[ [One,Five][Two,Three][Four,Six] ]
[ [One,Five][Two,Four][Three,Six] ]
[ [One,Five][Two,Six][Three,Four] ]
[ [One,Six][Two,Three][Four,Five] ]
[ [One,Six][Two,Four][Three,Five] ]
[ [One,Six][Two,Five][Three,Four] ]
]
答案 3 :(得分:0)
为简化问题,您可以将其分为两部分。
首先,生成所有组合。您可以使用以下函数(该想法来自Tom Butler's post):
function getCombinations(array $array)
{
$num = count($array);
$total = pow(2, $num);
for ($i = 1; $i < $total; $i++) {
$combination = [];
for ($j = 0; $j < $num; $j++) {
if (pow(2, $j) & $i) {
$combination[$j] = $array[$j];
}
}
yield $combination;
}
}
然后,您可以过滤所有组合,并仅保留其中包含两个元素的组合:
$keys = array_keys($arr);
$result = array_filter(
iterator_to_array(getCombinations($keys)),
function ($combination) {
return count($combination) === 2;
}
);
这是working demo。
答案 4 :(得分:-1)
在python中,它就像
一样简单result = itertools.permutations(keys, 2)
如果你想从头开始算法,你可以实现这样的递归函数。我在python中写了一些非常天真的东西,对不起,这不是PHP。
// permutation function
def permutations(my_list, target_len, curr_perm):
// base case
if len(curr_perm) = target_len:
print(curr_perm)
return
for item in my_list:
// don't add duplicates
if item in curr_perm:
continue
next_perm = curr_perm.copy()
next_perm.append(item)
// recursive call
permutations(my_list, target_len, next_perm)
// generate permutations of length 2
permutations(['one', 'two', 'three'], 2, [])