我有一个来自数据库的记录数组(尽管数据库与这个问题无关 - 它最终变成了一个“行”数组,每一行都是一个数组,字符串键对应于字段名)。例如:
$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...
);
我想要做的是将这个数组洗牌,但不知何故给予具有更新“创建”时间戳的项目更多“权重”。随机性不一定是完美的,确切的重量对我来说并不重要。换句话说,如果有一些快速而简单的技术对人类来说似乎是随机的,但在数学上并不是随机的,那我也没关系。另外,如果这对于时间戳的“无限连续统一”并不容易,那么将每条记录分配到一天或一周就可以了,只需根据它们在哪一天或哪一周进行加权。
相对快速/高效的技术是首选,因为这种随机化将发生在我网站中某个页面的每个页面加载上(但是如果不能有效地执行,我可以定期运行并缓存结果)
答案 0 :(得分: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越大(元素越新),开始时出现的可能性就越大。
例如,id=16
元素的 16x 比元素id=1
更早出现在结果列表中的机会。
答案 1 :(得分:0)
如何按日期将其拆分为块,随机化每个块,然后将它们作为一个列表重新组合在一起?
答案 2 :(得分: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()
答案 3 :(得分: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);