1

我想随机从 PHP 数组中提取值,而不是在从整个数组中提取所有值之前两次提取相同的值。

换句话说,如果我有数组......

 _____
| foo |
| bar |
| baz |
|_____|

...我想拉三次随机值而不拉两次相同的值,所以我可以...

1st:  foo  foo  bar  bar  baz  baz
2nd:  bar  baz  foo  baz  foo  bar
3rd:  baz  bar  baz  foo  bar  foo

...在我的三个单独的拉动上。

现在,我意识到我可以通过简单地从数组中删除选定的项目来做到这一点——如果我只从中拉一次。然而,事实并非如此。我需要数组保持完整,因为我想在一个循环中拉出所有值后再次重复随机拉动。

总结一下:我想以随机顺序从数组中迭代地提取所有值而不重复,直到所有项目都被拉出......然后无限期地重复该过程。


以为我通过将 PHP 数组中的每个选定值插入到 MySQL 表中来完成此操作,然后为每个后续数组拉取检查该表(如果拉取的值在 MySQL 表中,我重新运行该函数直到我得到一个从未选择过的值)。

这似乎实现了 get-all-values-without-duplicates 的目标,但在某些情况下我的输出变得有点古怪。

无论如何,这是我的代码,旨在实现预期的效果。我使用 jQuery (ajax) 每 7 秒调用一次 PHP 函数以获取新的数组值,并将该值保存在 MySQL 表中以供将来进行重复检查。当每个可用值都被提取后,我截断表格并重新开始。

Javascript(jQuery):

function cycle_facts() {        
    $.ajax({ url: 'lib/functions.php',
             data:    {setfact: 'yes'},
             type:    'post',
             success: function(output) {
                $('#header').html(output);
             }
    });
}

PHP:

function set_fact() {
    global $mysqli;

    $facts = get_facts(); //gets associative array with desired values to be randomly pulled

    /* see if all available values have been pulled, and truncate SQL table if so */
    $rows = $mysqli->query('select * from used_facts;');
    $rows = $rows->num_rows;
    if ($rows == sizeof($facts)) {
        $mysqli->query('truncate table used_facts;');
    }

    $fact = array_rand($facts);

    /* see if selected value has already been pulled in this cycle, and rerun function if so */
    $try = $mysqli->query('select * from used_facts where fact = \'' . $mysqli->real_escape_string($fact) . '\';');
    if ($try->num_rows >= 1) {
        set_fact();
    }
    else {
        $mysqli->query('insert into used_facts (fact) values (\'' . $mysqli->real_escape_string($fact) . '\');'); //insert newly selected value into SQL table for future duplication checking
    }

    echo $fact . '|' . $facts[$fact]; //return selected value to jQuery for display
}

所以我可能可以通过一些调整来使用这种方法,但这个问题本身让我很感兴趣,想知道是否有一种更简单、更直接的方法,stackoverflow 上的优秀人员已经使用过。

谢谢!

4

1 回答 1

9

这将以随机顺序为您提供数组的每个元素,而无需重新组织原始数组

foreach (shuffle($arr) as $elem) {
  echo $elem;
}

如果您想提高 shuffle 的真实随机性,请查看评论以获取更多详细信息。我特别喜欢Fishes Yates Shuffle但你可以做一些研究和任何你喜欢的工具:)


PHPshuffle会重新排序你的数组的索引——也就是说,它会改变输入数组。

如果您想保留输入数组并对其进行打乱复制,我已经花时间为您实现 Fisher-Yates “由内而外”算法。

function pureshuffle (array $xs): array {
  $acc = [];
  for ($i = 0; $i < count($xs); $i++) {
    $j = rand(0, $i);
    if ($j != $i) $acc[$i] = $acc[$j]; 
    $acc[$j] = $xs[$i];
  }
  return $acc;
}

$data = [1,2,3,4,5,6,7];

print_r(pureshuffle($data));
// [2,1,4,6,5,7,3]

print_r($data);
// [1,2,3,4,5,6,7]

或者,您可以使用排序 MySQL 结果

ORDER BY RAND()

其性能将取决于许多其他因素,但如果查询足够简单并且结果足够小,那应该不是问题。

如果您想采用这种方法,请快速搜索一下。您会发现很多在 SQL 中优化随机排序的信息和技巧。

于 2013-06-19T19:59:31.870 回答