2

Possible Duplicate:
Generating random results by weight in PHP?

i have made a database in which i store the name and the link of rss feeds.i have made the rss reader and everything is ok till now.I want to make a news scroller which will show the articles of the feeds.But i want to give to the feeds some weight values in order every feed to be selected according to its importance for me and automatically when a feed is selected from those in the database its articles only will be showed in the scroller.Any ideas of how can i do that???Thanks in advance..

p.s. my problem is how can i do aytomatically the random weighted choice of the feeds from the database and not how to show the articles of the feeds(i have done this part).

Community
  • 1
  • 1
olaf36
  • 87
  • 1
  • 12

2 Answers2

6

Two ways to do this, that I can think of from the top of my head:

Option 1: Fill a new array with the key values from the set of data, where the weight determines how often an item is repeated. The proportion in this array then matches the weighted distribution. Simply grab using $arr[array_rand($arr)]. While simple and easy to understand, this will explode in your face if there are a LOT of items, or if the weight values are really high.

$weighted = array();
foreach($items as $item) {
    array_merge($weighted, array_fill(0, $item['weight'], $item['value']);
}
$result = $weighted[array_rand($weighted)];

Option 2. Sum the weights. Pick a random number between 0 and sum-of-weights. Loop over the elements in the dataset, compare against the random number you picked. As soon as you hit one that is equal to or bigger then the random index, select that element.

function findRandomWeighted(array $input) {
   $weight = 0;
   // I'm assuming you can get the weight from MySQL as well, so this loop really should not be required. In that case $weight becomes a parameter.
   foreach($items as $item) {
      $weight += $item['weight'];
   }

   $index = rand(1, $weight);
   foreach($items as $item) {
      $index -= $item['weight'];
      if($index <= 0) { return $item['value'] }
   }

   return null;
}

Following our conversation in the comments below, here is a Pastebin with the code in it:

http://pastebin.com/bLbhThhj

kander
  • 4,146
  • 1
  • 20
  • 41
  • +1 The second option would probably be faster, and possibly easier to implement. – ughoavgfhw Jan 07 '11 at 06:38
  • No, the database is not going to have many entries.10 feeds at most...The db has only 3 fields.Id,name of the feed,url of the feed.To be honest i do not understand the first solution you gave me that much. I will try the second one as a first approach..I am not pro in php and it looks easier to me..Thanks!! – olaf36 Jan 07 '11 at 06:50
  • Hi user566487 - what the first example does: If you have an array like this `$feeds = array(array('value'=>'Feed 1', 'weight'=>2), array('value'=>'Feed 2', 'weight'=>1), array('value'=>'Feed 3', 'weight'=>5))`, it creates a secondary array like: `array('Feed 1', 'Feed 1', 'Feed 2', 'Feed 3', 'Feed 3', 'Feed 3', 'Feed 3', 'Feed 3');` Each element is inserted as often as its weight indicates. Then you can simply pull a random one out, using array_rand(), and it will be random according to the weights you specified. But if you think the second is simpler, please use that one as it is better :) – kander Jan 07 '11 at 18:27
  • Sorry my friend but i am too confused.I don't know how to make the script taking a feed from my database.Of course with an expression like SELECT * from feeds where feed_id=the variable which produces the random weighted value.But i am not familiar with the idea of random weighted value.I mean that i dont know how to merge the idea you proposed above with my database. – olaf36 Jan 10 '11 at 10:41
  • Also, is it effective to add another field in the database with the weight and there add the values.But again i don't know how to combine them – olaf36 Jan 10 '11 at 10:45
  • Could you add the CREATE statement for your database to the question? I'll see if I can find a few moments to whip up code that matches your database schema, and add some more comments. – kander Jan 10 '11 at 10:49
  • CREATE TABLE IF NOT EXISTS `feeds` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `url` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; This my database schema.Thnx for your help my friend.. – olaf36 Jan 10 '11 at 10:57
  • Hi User566487 - see the latest edit to the answer. I've added a Pastebin.com link. There is SQL at the top to add the weights, then the function from my post, followed by example code that shows the random distribution by selecting a random feed 1000 times. Does this help? – kander Jan 10 '11 at 18:43
  • May ask you something? in this part of the code UPDATE `test`.`feeds` SET `weight`=1 WHERE `id`='1' weight=1 what does it represent?You have just added a value to this feed equal to 1?? or this mean for example that it is normal selection and the feed you gave it a weight=6 it is 6 times more possible to be selected than a feed with weight=1? – olaf36 Jan 11 '11 at 03:37
  • Exactly. The meaning of the weight is only how frequent it will be selected compared to other items in the list. So, as you say, something with Weight = 6 is six times as likely to be chosen as a weight = 1. – kander Jan 11 '11 at 06:38
  • http://pastebin.com/gsvFcg5c In this link it's a new script i made with some changes to the original script in order to show in the screen which feed is chosen.I added a weight field in the database in which i gave values for every feed.And i executed the script 250 times and it gave me reasonable results.I would like to ask you a few things about the code.In the lines 11-15 what does the code exactly do.And in the lines where you added a comment //Test what the code is doing there too? – olaf36 Jan 11 '11 at 07:10
  • Thanks my friend for your help.I made the script to be executed after specific time.THe last thing i would like to ask you is if you can to explain me some lines of the code you made..I can't understand what exactly they do..in the file you uploaded in pastebin http://pastebin.com/bLbhThhj the lines 27-31 and 43-51.thanks in advance.... – olaf36 Jan 13 '11 at 00:33
  • Hi User - good to hear you got it to work for you. I've tried to write an explanation... http://pastebin.com/qTTEWK8u but please, try to loop through the code. Add echo's where you want to understand what's going on. The best way to understand is to just look at the variables as they pass through the script. A debugger (such as Zend Studio or PHPStorm, combined with Zend Debugger or XDebug) can really help in figuring out what a piece of code does. – kander Jan 13 '11 at 14:09
0

You can find fast algorithm implemented and described - weighted random (in javascript but can be rewritten to PHP in a few minutes I think). It is much faster than loop through the array.

Sergiy
  • 9
  • 1
  • You shouldn't just give a link to another site as an answer, since the site may go out of date in the future. Instead, click the "edit" link on this answer and include the essential parts of the solution from that page here. See: http://meta.stackexchange.com/q/8259 – Peter O. Oct 20 '12 at 05:32