0

我有一个来自数据库的记录数组(尽管数据库与这个问题无关——它最终变成了一个“行”数组,每一行都是一个数组,其中字符串键对应于字段名)。例如:

$items = array(
    1 => array('id' => 1, 'name' => 'John', 'created' => '2011-08-14 8:47:39'),
    2 => array('id' => 2, 'name' => 'Mike', 'created' => '2011-08-30 16:00:12'),
    3 => array('id' => 5, 'name' => 'Jane', 'created' => '2011-09-12 2:30:00'),
    4 => array('id' => 7, 'name' => 'Mary', 'created' => '2011-09-14 1:18:40'),
    5 => array('id' => 16, 'name' => 'Steve', 'created' => '2011-09-14 3:10:30'),
    //etc...
);

我想要做的是打乱这个数组,但以某种方式给具有更新“创建”时间戳的项目更多“权重”。随机性不一定是完美的,确切的重量对我来说并不重要。换句话说,如果有一些快速简单的技术对人类来说有点随机,但在数学上不是随机的,我可以接受。此外,如果这对于时间戳的“无限连续体”来说不容易做到,那么我可以将每条记录分配给一天或一周,并根据它们所在的日期或星期进行加权.

一种相对快速/高效的技术更可取,因为这种随机化将发生在我网站中某个页面的每个页面加载时(但如果无法有效地做到这一点,我可以定期运行它并缓存结果)。

4

4 回答 4

1

您可以使用例如。这个比较函数:

function cmp($a, $b){
    $share_of_a = $a['id'];
    $share_of_b = $b['id'];
    return rand(0, ($share_of_a+$share_of_b)) > $share_of_a ? 1 : -1;
}

然后像这样使用它:

usort($items, 'cmp');

它根据它们的 ID比较数组的两个元素(这更容易,并且它们是根据创建日期分配的 - 较新的元素具有更大的 ID)。比较是随机进行的,每个元素有不同的成功机会,给新元素更多的机会。ID 越大(元素越新),它出现在开头的机会就越大

例如,元素 with比元素更早出现在结果列表中的id=16机会多16 倍。id=1

于 2011-11-13T04:39:27.043 回答
0

按日期将其拆分成块,随机化每个块,然后将它们重新组合成一个列表怎么样?

于 2011-11-13T04:34:14.043 回答
0

在受到@Tadeck 回复的部分启发后,我想出了一个解决方案。这有点啰嗦,如果有人可以简化它,那就太好了。但它似乎工作得很好:

//Determine lowest and highest timestamps
$first_item = array_slice($items, 0, 1);
$first_item = $first_item[0];
$min_ts = strtotime($first_item['created']);
$max_ts = strtotime($first_item['created']);
foreach ($items as $item) {
    $ts = strtotime($item['created']);
    if ($ts < $min_ts) {
        $min_ts = $ts;
    }
    if ($ts > $max_ts) {
        $max_ts = $ts;
    }
}

//bring down the min/max to more reasonable numbers
$min_rand = 0;
$max_rand = $max_ts - $min_ts;

//Create an array of weighted random numbers for each item's timestamp
$weighted_randoms = array();
foreach ($items as $key => $item) {
    $random_value = mt_rand($min_rand, $max_rand); //use mt_rand for a higher max value (plain old rand() maxes out at 32,767)
    $ts = strtotime($item['created']);
    $ts = $ts - $min_ts; //bring this down just like we did with $min_rand and $max_rand
    $random_value = $random_value + $ts;
    $weighted_randoms[$key] = $random_value;
}

//Sort by our weighted random value (the array value), with highest first.
arsort($weighted_randoms, SORT_NUMERIC);

$randomized_items = array();
foreach ($weighted_randomsas $item_key => $val) {
    $randomized_items[$item_key] = $items[$item_key];
}

print_r($randomized_items);
于 2011-11-14T01:03:10.940 回答
0
//$array is your array
$mother=array();
foreach($array as $k->$v) $mother[rand(0,count($array))][$k]=$v;
ksort($mother);
$child=array();
foreach($mother as $ak->$av)
foreach($av as $k->$v) $child[$k]=$v;
$array=$child;

或者你可以使用 shuffle()

于 2011-11-13T04:37:02.370 回答