Php 如何从排除一个值的数组中随机选择?

Php 如何从排除一个值的数组中随机选择?,php,arrays,Php,Arrays,随着假期的慢慢临近,又到了捡稻草的时候了。我们总是从包含每个人姓名的盒子里挑选一张纸。然而,今年我想通过使用PHP解决从框中选择自己名字的问题 我有一个名为ex的数组: $names = [ 'John', 'Jane', 'Joe', 'Matt', 'Steve', 'Anne', 'Karin' ]; 对于这些名字中的每一个,我想随机选择4个名字,这样每个人最后都有4个名字,他们将不得不为此购买礼物 问题 我被卡住了。我已经想了一百

随着假期的慢慢临近,又到了捡稻草的时候了。我们总是从包含每个人姓名的盒子里挑选一张纸。然而,今年我想通过使用PHP解决从框中选择自己名字的问题

我有一个名为ex的数组:

$names = [
    'John',
    'Jane',
    'Joe',
    'Matt',
    'Steve',
    'Anne',
    'Karin'
];
对于这些名字中的每一个,我想随机选择4个名字,这样每个人最后都有4个名字,他们将不得不为此购买礼物

问题 我被卡住了。我已经想了一百万种方法,但我就是想不出什么

到目前为止我都试过了
  • 使用foreach
  • 使用
    array\u rand()
  • 移动阵列
问题是,一个人不应该选择自己的名字,每个人都应该被选择次数均等(4)

更新 一些很棒的答案已经发布了。但我不确定这是否对每个人都公平。最后每个人都应该从4个不同的人那里得到4份礼物

我正在考虑将每个名称添加到
$names
数组中4次,然后应用您的一个答案。我做得对吗

更新2 我现在尝试的是:

function select_rand($array, $exclude_array) {
    $diff = array_diff($array, $exclude_array);
    return $diff[array_rand($diff, 1)];
}

$workArray = [
    '0' => $names,
    '1' => $names,
    '2' => $names,
    '3' => $names,
];

foreach ($names as $k => $name) {
    $i = 0;
    $new[$name] = array();
    while ($i < 4) {
        $value = select_rand($workArray[$i], array_merge($new[$name], array($name)));
        if (($key = array_search($value, $workArray[$i])) !== false) {
            unset($workArray[$i][$key]);
        }
        $new[$name][] = $value;
        $i++;
    }
}
函数选择随机($array,$exclude\u array){
$diff=array\u diff($array,$exclude\u array);
返回$diff[array_rand($diff,1)];
}
$workArray=[
“0”=>$names,
“1”=>$names,
“2”=>$names,
'3'=>$names,
];
foreach($k=>$name){
$i=0;
$new[$name]=array();
而($i<4){
$value=select_rand($workArray[$i],array_merge($new[$name],array($name));
if(($key=array\u search($value,$workArray[$i]))!==false){
未设置($workArray[$i][$key]);
}
$new[$name][]=$value;
$i++;
}
}

这只在少数CAE中起作用。

我会使用洗牌和数组\u切片来完成这项工作:

$names = [
    'John',
    'Jane',
    'Joe',
    'Matt',
    'Steve',
    'Anne',
    'Karin'
];

foreach ($names as $name) {
   // working array
   $working = $names;
   // remove current name from array,no one wants to buy presents for him/her self..
   unset($working[$name]);
   shuffle($working);
   $people = array_slice($working, 0, 4);
   echo $name . ' has to buy presents for:';
   var_dump($people);
}
这有助于-

function select_rand($array, $exclude_array) {
    $diff= array_diff($array, $exclude_array);
    return $diff[array_rand($diff, 1)];
}

$names = array(
    'John',
    'Jane',
    'Joe',
    'Matt',
    'Steve',
    'Anne',
    'Karin'
);
foreach($names as $name)
{
    $i = 0;
    $new[$name] = array();
    while($i < 4) {
        $new[$name][] = select_rand($names, array_merge($new[$name], array($name)));
        $i++;
    }
}

您可以创建自定义函数,如

$names = [
    'John',
    'Jane',
    'Joe',
    'Matt',
    'Steve',
    'Anne',
    'Karin'
];

$my_name = "John";
$limit = 4;

function get_name($arr,$your_name,$limit){
    $key = array_flip($arr)[$your_name];
    unset($arr[$key]);
    $rand_keys = array_rand($arr,$limit);
    $result = array_intersect_key($arr, array_flip($rand_keys));
    return implode(',',$result);
}

echo get_name($names,$my_name,$limit);

我认为,如果你想让礼物平均分配给每个人,你需要有更多的控制权。无论如何,在这段代码中,我记录了每个人的礼物数量。我用零初始化它:
$presents=array\u fill\u key($names,0)。然后在每次选择之后,我更新了这个数字
$presents[$key]++

<?php
$names = array(
    'John',
    'Jane',
    'Joe',
    'Matt',
    'Steve',
    'Anne',
    'Karin'
);

$presents_number = 4;
// initialization 
$presents = array_fill_keys($names, 0);
$names_names = array();
foreach ($names as $i => $picker)  {
    $box = $names;
    unset($box[$i]);
    
    // filter out the people with maximum presents:
    foreach ($presents as $key => $number) {
        if (($presents[$key] > $presents_number-1) && in_array($key, $box)) {
            $box = array_diff($box, array($key));
        }
    }

    // shuffle the box and select 4 top
    shuffle($box);
    $selection = array_slice($box, 0, $presents_number);
    foreach ($selection as $key) {
        $presents[$key]++;
    }
    $names_names[$picker] = $selection;
}

echo "<pre>";
print_r($names_names);
echo "</pre>";

array\u rand()
array\u diff()
这看起来很棒,而且非常接近。但每个人都有4个名字。这4个必须是唯一的。虽然名称数组包含30人,而不是7人,如果这是有用的。效果很好,但如何防止Karin从每个人那里得到礼物?@Peter检查更新。只需将Karin添加到要排除的数组中即可。:)加入Karin不能解决我的问题,是吗?其他人仍然可以得到4份以上的礼物。那么一个人应该得到多少份礼物?每个名字的限制是什么?每个人应该有4个名字。但每个人只能被挑选4次。
<?php
$names = array(
    'John',
    'Jane',
    'Joe',
    'Matt',
    'Steve',
    'Anne',
    'Karin'
);

$presents_number = 4;
// initialization 
$presents = array_fill_keys($names, 0);
$names_names = array();
foreach ($names as $i => $picker)  {
    $box = $names;
    unset($box[$i]);
    
    // filter out the people with maximum presents:
    foreach ($presents as $key => $number) {
        if (($presents[$key] > $presents_number-1) && in_array($key, $box)) {
            $box = array_diff($box, array($key));
        }
    }

    // shuffle the box and select 4 top
    shuffle($box);
    $selection = array_slice($box, 0, $presents_number);
    foreach ($selection as $key) {
        $presents[$key]++;
    }
    $names_names[$picker] = $selection;
}

echo "<pre>";
print_r($names_names);
echo "</pre>";