假设您在数组中有一组项目。
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配对。 因此,必须存在与项目一样多的关系。
答案 0 :(得分:3)
复制数组。
在一个阵列上调用shuffle
。
然后:
array_pop
关闭每个数组中的项目以形成一对。修改强>
根据您的额外条件,您需要检查每对都不存在。如果它(在第三阶段)你可以尝试采取不同的组合(弹出第一和第三{弹出第一,第二,第三和第二次推回}}但你最后可能仍然会得到一个无效的组合,所以需要重新开始。
答案 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);