Select a user according to set probability

2019-08-20 03:01发布

My database stores info about users, their groups, and relationships. One of the columns, fcount, in the users table tracks the number of relationships each user has had within their current group; it starts at 0, and I increment it when appropriate.
I need to write a script that selects all users in a given group and then randomly selects one of them with the probability of being selected being based on the number of relationships one has had; fewer relationships means a greater probability.

Currently, I accomplish this, minus the probability part, with this code:

$query = "SELECT uid FROM users WHERE groupid=:gid AND status='1'";
...
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
    $friends[] = $row[0];
}

foreach ($users as $value) {
    $key = array_search($value, $friends);
    unset($friends[$key]);
    shuffle($friends);
    $newrel = end($friends);
    $user = $value;
    $friends[] = $value;

    $query = "UPDATE users SET rel=:newrel WHERE uid=:uid";
    $query_params = array(':newrel' => $newrel, ':uid' => $user );
... }

I am thinking that the easiest way to adjust probability would be to edit the $friends array so that users show up more than once. So, users with an fcount of 0 will be repeated in the array 5 times, and users with an fcount of 1 are repeated 3 times. [Maybe this isn't the best way to handle it, but it makes sense to me and fits with the code I already have. You're free to offer a better scheme.]

What I haven't managed to figure out is how to take the array of users and multiply the entries of the users who ought to be multiplied.

SELECT uid, fcount FROM users WHERE groupid=:gid AND status='1';

returns an array reflective of this table:

+-----+--------+
| uid | fcount |
+-----+--------+
| 105 |      3 |
| 106 |      2 |
| 107 |      0 |
| 108 |      0 |
| 109 |      1 |
+-----+--------+

which then turns into an array like this:

array(15) { 
[0]=> string(3) "105" 
[1]=> string(3) "106" 
[2]=> string(3) "107" 
[3]=> string(3) "107" 
[4]=> string(3) "107" 
[5]=> string(3) "107" 
[6]=> string(3) "107" 
[7]=> string(3) "108" 
[8]=> string(3) "108" 
[9]=> string(3) "108" 
[10]=> string(3) "108" 
[11]=> string(3) "108"
[12]=> string(3) "109" 
[13]=> string(3) "109" 
[14]=> string(3) "109" 
}  

It seems to me that this could be accomplished with a foreach that pushes each userid n times into a new array according to if statements in the loop. I'll try to construct it, even though I'm likely to fail.

2条回答
smile是对你的礼貌
2楼-- · 2019-08-20 03:12
$problist = array();
foreach ($row as $value) {
    if ($value['fcount'] == 0) {
        array_push($problist, $value['uid'], $value['uid'], $value['uid'], $value['uid'], $value['uid']);
    } elseif ($value['fcount'] == 1) {
        array_push($problist, $value['uid'], $value['uid'], $value['uid']);
    } elseif ($value['fcount'] >= 2) {
        $problist[] = $value['uid'];
    }
}
查看更多
乱世女痞
3楼-- · 2019-08-20 03:22

Easiest way calculating a probability in a general occasion

$relations = 10;
$chance = rand(1,100);
if ($chance <= $relations) {
// success
}

In this case, the more the relations are, the bigger the probability comes, it's like if $relations = 99, you will have like 99% probability to hit this user with relations=99

查看更多
登录 后发表回答