使用PHP,随机配对一组项目,而不是与其自身配对,没有直接配对

时间:2010-09-21 07:40:19

标签: php algorithm random

假设您在数组中有一组项目。

A,B,C,D,E,F,G,H

使用PHP,如何将这些字母随机配对而不将它们与自己的副本配对?

如:

 A->pairedLetter = G
 B->pairedLetter = C
 C->pairedLetter = E
 D->pairedLetter = A
 E->pairedLetter = B
 F->pairedLetter = D
 G->pairedLetter = F

依旧......

编辑: 哦,而且,如果A与F配对,F不能与A配对。 因此,必须存在与项目一样多的关系。

7 个答案:

答案 0 :(得分:3)

复制数组。 在一个阵列上调用shuffle。 然后:

  1. 检查第一个元素是否不同(如果它们是切换一个数组的前两个元素)。
  2. array_pop关闭每个数组中的项目以形成一对。
  3. 如果项目相同,请从一个阵列中弹出两个并配对,然后从另一个阵列中弹出两个。
  4. 修改

    根据您的额外条件,您需要检查每对都不存在。如果它(在第三阶段)你可以尝试采取不同的组合(弹出第一和第三{弹出第一,第二,第三和第二次推回}}但你最后可能仍然会得到一个无效的组合,所以需要重新开始。

答案 1 :(得分:3)

这个怎么样?

// input array
$arr = array('A','B','C','D','E','F');
// result array
$res = array();
// get first element and save it
$first = $ele1 = array_shift($arr);
while(count($arr)) {
    // get random element
    $ele2 = array_rand($arr);
    // associate elements
    $res[$ele1] = $arr[$ele2];
    // random element becomes next element
    $ele1 = $arr[$ele2];
    // delete the random element
    array_splice($arr, $ele2, 1);
}
// associate last element woth the first one
$res[$ele1] = $first;

print_r($res);

输出:

Array
(
    [A] => B
    [B] => F
    [F] => E
    [E] => D
    [D] => C
    [C] => A
)

使用偶数个元素数组以及奇数。

使用Chris'算法进行更新:

$arr = array('A','B','C','D','E','F');
shuffle($arr);
$res=array();
for($i=0;$i<count($arr);$i++) {
  $res[$arr[$i]] = $arr[$i+1];
}
$res[$arr[count($arr)-1]] = $arr[0];

答案 2 :(得分:3)

根据你的约束,它是否必须完全随机?如果您愿意添加另一个约束,那么您可以使问题变得非常简单。如果你愿意这样做,以便映射都形成一个循环,那么你可以只是将数组洗牌,然后将元素一个pont在两个,两个点在三个,最后一个元素指向第一个。你将保证没有元素可以自己(除非数组只有一个元素),没有元素指向指向它的元素(除非数组只有两个元素)并且没有任何元素指向一件事。

您正在限制您的结果集,因此会丢失一定数量的随机元素,但如果您对此感到满意,那么它非常简单。

答案 3 :(得分:1)

$array = array(
    'A','B','C',
    'D','E','F',
    'G','H','I','J'
);
$new = array();

if(count($array) % 2 != 0)
{
    array_pop($array); // Got to remove 1 element to make them even.
}

foreach($array as $item)
{
    $_t = array_pop($array);
    //Key
    if(!isset($new[$item]))
    {
        $new[$item] = $_t;
        $new[$_t] = $item;
    }
}


var_dump($new);

这将打印:

array(10){
    ["A"]=> string(1) "J"
    ["J"]=> string(1) "A"
    ["B"]=> string(1) "I"
    ["I"]=> string(1) "B"
    ["C"]=> string(1) "H"
    ["H"]=> string(1) "C"
    ["D"]=> string(1) "G"
    ["G"]=> string(1) "D"
    ["E"]=> string(1) "F"
    ["F"]=> string(1) "E"
}

它的工作方式是循环值并同时删除一个值,因此你总是一次有2个值但同时将数组缩小为1。

然后当我们设置新键时将它们都设置为新数组,所以下次循环迭代时如果相同的值返回它就会被丢弃:)

答案 4 :(得分:0)

我尝试使用原始数组的副本并使用array_rand(),但如果它找到与我迭代相同的项目,我必须再次运行array_rand(),这可能会陷入无限循环。

我很难过,必须有一种优雅的方式来做到这一点。

答案 5 :(得分:0)

$arrayValues = range('A','H');
shuffle($arrayValues);
while (count($arrayValues) > 0) {
   echo array_pop($arrayValues),' is matched with ',array_pop($arrayValues),'<br />';
}

修改

对问题的更改

$arrayValues = range('A','H');
$tmpArrayValues = $arrayValues;
$pairs = array();
shuffle($tmpArrayValues);
foreach($arrayValues as $arrayValue) {
    $tmpValue = array_pop($tmpArrayValues);
    while (($arrayValue == $tmpValue) || ((isset($pairs[$tmpValue])) && ($pairs[$tmpValue] == $arrayValue))) {
        array_unshift($tmpArrayValues,$tmpValue);
        $tmpValue = array_pop($tmpArrayValues);
    }
    $pairs[$arrayValue] = $tmpValue;
}

foreach($pairs as $key => $value) {
   echo $key,' is matched with ',$value,'<br />';
}

答案 6 :(得分:0)

在数组上使用shuffle函数并检查映射是否有效(A不映射到A,如果A映射到B,则B不映射到A)。以下应该做你想要的:

$values = array('A','B','C','D','E','F','G');
$new_values = array('A','B','C','D','E','F','G');

$random = shuffle($new_values);
//randomly shuffle the order of the second array
$mappings = array();

$validMappings = false;
//continue to retry alternative mappings until a valid result is found
while(!$validMappings) {
   //set the mappings from $values to $new_values
   for($i = 0; $i < count($values); $i++) {
        $mappings[$values[$i]] = $new_values[$i];
    }

    $validMappings = true;
    //check validity of the current mapping
    foreach ($mappings as $key=>$value) {
        if($mappings[$key] == $mappings[$value]) {
            $validMappings = false;
            break;
        }
    }
    //if false shuffle the new values and test again
    if(!$validMappings) {
        $random = shuffle($new_values);
    }
}
print_r($mappings);