如何随机化 PHP 记录数组,为最近的项目赋予更多权重?

发布于 2024-12-15 08:22:53 字数 872 浏览 3 评论 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...
);

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

因为这种随机化将发生在我的网站中某个页面的每个页面加载上(但如果不可能有效地做到这一点,我可以定期运行它并缓存结果)。

I have an array of records from a database (although the database is irrelevant to this question -- it eventually becomes an array of "rows", each row is an array with string keys corresponding to the field name). For example:

$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...
);

What I want to do is shuffle this array, but somehow give more "weight" to items with a more recent "created" timestamp. The randomness does not have to be perfect, and the exact weight does not really matter to me. In other words, if there's some fast and simple technique that kinda-sorta seems random to humans but isn't mathematically random, I'm okay with that. Also, if this is not easy to do with an "infinite continuum" of timestamps, it would be fine with me to assign each record to a day or a week, and just do the weighting based on which day or week they're in.

A relatively fast/efficient technique is preferable since this randomization will occur on every page load of a certain page in my website (but if it's not possible to do efficiently, I'm okay with running it periodically and caching the result).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

反目相谮 2024-12-22 08:22:53

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

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 的元素比元素 id=1 出现在结果列表前面的机会多 16 倍

You can use eg. this comparison function:

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;
}

and then use it like this:

usort($items, 'cmp');

It compares two elements of an array based on their IDs (it is easier and they are assigned based on the date of creation - newer elements have bigger IDs). The comparison is done randomly, with different chances of success for each element, giving more chances to the newer elements. The bigger the ID (the newer the element), the more chances it has to appear at the beginning.

For example element with id=16 has 16x more chances than element id=1 to appear earlier on the resulting list.

め可乐爱微笑 2024-12-22 08:22:53

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

What about splitting it up into chunks by date, randomizing each chunk, and then putting them back together as one list?

伪装你 2024-12-22 08:22:53
//$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()

//$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;

or you can use shuffle()

姐不稀罕 2024-12-22 08:22:53

在受到@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);

After being partially inspired by the response from @Tadeck , I came up with a solution. It's kind of long-winded, if anyone could simplify it that would be great. But it seems to work just fine:

//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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文