简体   繁体   中英

PHP: Select random weighted index from Array

I know there are many similar questions here, but I am having trouble implementing it correctly in my code.

I am pulling in id, ip, port and weight from a database and from there I want to be able to select a random ip that has a very low weight (not used recently).

Here is a subset of a result set. The full list is here .

id  ip  port  weight  tries
174  127.0.0.1  3128  906  0
101  127.0.0.1  8080  629  2
123  127.0.0.1  3128  433  3
226  127.0.0.1  3128  393  1
82  127.0.0.1  8080  333  2
252  127.0.0.1  8080  276  3
253  127.0.0.1  3128  209  0
240  127.0.0.1  3129  204  1
249  127.0.0.1  3128  190  0
261  127.0.0.1  8888  165  1
120  127.0.0.1  3128  161  3
188  127.0.0.1  8080  149  0
265  127.0.0.1  8080  108  1
275  127.0.0.1  8080  104  0
63  127.0.0.1  8080  95  2
196  127.0.0.1  8080  79  2
248  127.0.0.1  8080  73  1
223  127.0.0.1  8000  72  3
88  127.0.0.1  3128  69  3
422  127.0.0.1  8080  47  0

Going down the list I have many ip's that just aren't being selected and with a majority few being used over and over again.

Thanks to Yaniro, I came up with a better solution.

My code:

private function _weighted_random_simple($proxies)
{
    foreach ($proxies as $proxy) {
        $weight[] = $proxy['weight'];           
    }

    array_multisort($weight, SORT_ASC, $proxies);

    // Define the custom sort function
    $proxie = array(
        'id' => $proxies[0]['id'], 
        'ip' => $proxies[0]['ip'], 
        'port' => $proxies[0]['port'], 
        'weight' => $proxies[0]['weight'], 
        'tries' => $proxies[0]['tries']
    );

    return $proxie;
}   

Can anyone offer a better piece of code?

Thanks

You could sort the array by the weight in ascending order and then select the first element which will guarantee the selection of the least busy server.

You code seems fine and you could also use: usort() or uasort() like so:

function cmp( $a, $b )
{
    if ( $a[ 'weight' ] == $b[ 'weight' ] )
    {
        return 0;
    }

    return ( $a[ 'weight' ] < $b[ 'weight' ] ) ? -1 : 1;
}

usort( $fruits, "cmp" );

If you want the comparison function to be a part of you class do something like this:

class YourClass
{
    static function cmp( $a, $b )
    {
        if ( $a[ 'weight' ] == $b[ 'weight' ] )
        {
            return 0;
        }

        return ( $a[ 'weight' ] < $b[ 'weight' ] ) ? -1 : 1;
    }

    private function _weighted_random_simple( $proxies )
    {
        usort( $proxies, array( "YourClass", "cmp" ) );
        return $proxies[ 0 ];
    }
}

Or just loop through the array, find the lowest weight and return its index:

$lowest = -1;
$index  = 0;

for ( $i = 0; $i < count( $proxies ); ++$i )
{
    if ( $proxies[ $i ][ 'weight' ] < $lowest || $lowest == -1 )
    {
        $lowest = $proxies[ $i ][ 'weight' ];
        $index  = $i;
    }
}

return $proxies[ $index ];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM