Forum Moderators: coopster

Message Too Old, No Replies

array rand

array_rand problem

         

lj2007

7:29 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



I have the following script to parse an XML/RSS feed. However what i want to do is to have three random items show up - how would i modify the following? I have tried using array_rand but this does not seem to work - any ideas?

THanks!

<?php

define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
define('MAGPIE_DIR', 'magpie/');

require_once(MAGPIE_DIR.'rss_fetch.inc');

if ( isset($_GET['url']) ) {
$url = $_GET['url'];
}
else {
$url = 'http://www.example.com/rss/sportonline_uk_edition/front_page/rss.xml';
}

$rss = fetch_rss( $url );

$items = array_rand($rss->items,3);

if ($rss) {

foreach ($items as $item) {
$href = $item['link'];
$title = $item['title'];
$description = $item['description'];
echo "<p class='dark'>> <b><a class='dark' href=$href>$title</a></b><br />$description</p>";
}

}
else {
echo "Error: " . magpie_error();
}
?>

[edited by: dreamcatcher at 11:11 am (utc) on Aug. 20, 2007]
[edit reason] Use example.com, thanks. [/edit]

WesleyC

7:48 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



<?php

//This just selects a random entry from $rss->items

$count = 3;

for ($i = 0, $i < $count, $i++)
{
$items[] = $rss->items[rand(0, count($rss->items))];
}

//Item handling/parsing code here

lj2007

8:02 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Ok i now have the following - but it is just generating a random number of items. What i want is three items but i want them to be random...?

<?php

define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
define('MAGPIE_DIR', 'magpie/');

require_once(MAGPIE_DIR.'rss_fetch.inc');

if ( isset($_GET['url']) ) {
$url = $_GET['url'];
}
else {
$url = 'http://www.example.com/rss/sportonline_uk_edition/front_page/rss.xml';
}

$rss = fetch_rss( $url );

$count = 3;

for ($i = 0, $i < $count, $i++;

$items[] = $rss->items[rand(0, count($rss->items))];
)

if ($rss) {

foreach ($items as $item) {
$href = $item['link'];
$title = $item['title'];
$description = $item['description'];
echo "<p class='dark'>> <b><a class='dark' href=$href>$title</a></b><br />$description</p>";
}

}
else {
echo "Error: " . magpie_error();
}
?>

[edited by: dreamcatcher at 11:11 am (utc) on Aug. 20, 2007]
[edit reason] Use example.com, thanks. [/edit]

WesleyC

8:11 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Your "for" syntax is messed up.

for ($i = 0, $i < $count, $i++;

should be

for ($i = 0; $i < count; $i++)

and the line assigning a random RSS item to the $items[] array should be within { and }.

[edited by: WesleyC at 8:12 pm (utc) on Aug. 17, 2007]

lj2007

8:16 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Thanks,

now i am getting "Warning: Invalid argument supplied for foreach()" in the line:

foreach ($items as $item) {

Any ideas?

WesleyC

8:31 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Can you post the code you have from $count = 3 up until the line you're getting the error?

lj2007

8:32 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



$count = 3;

for ($i = 0, $i < $count, $i++;

$items[] = $rss->items[rand(0, count($rss->items))];
)

if ($rss) {

foreach ($items as $item) {

lj2007

8:33 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Sorry that's wrong its:

$count = 3;

for ($i = 0; $i < count; $i++)

{$items[] = $rss->items[rand(0, count($rss->items))];}

if ($rss) {

foreach ($items as $items {

lj2007

8:38 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



that was wrong too!

$count = 3;

for ($i = 0; $i < count; $i++)

{$items[] = $rss->items[rand(0, count($rss->items))];}

if ($rss) {

foreach ($items as $items) {

lj2007

9:17 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Ahh! Got it:

for ($i = 0; $i < count; $i++)

should be:

for ($i = 0; $i < $count; $i++)

? is that right?

It seems to work but occasionally one of the 3 items is blank...hmmm...any ideas? Am i missing something?

$count = 3;

for ($i = 0; $i < $count; $i++)

{$items[] = $rss->items[rand(0, count($rss->items))];}

if ($rss) {

foreach ($items as $item) {

lj2007

9:18 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Also...sometimes the same item shows up twice - is there any way of stopping this?

Thanks!

WesleyC

9:23 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



Ahh, yes, I'd missed that.

{
$items[] = $rss->items[rand(0, count($rss->items)- 1)];
}

In order to avoid duplicate entries, just check the $items array to see if the rss item selected is already there.

lj2007

9:26 pm on Aug 17, 2007 (gmt 0)

10+ Year Member



How do i code that?

Thanks again!

lj2007

10:34 am on Aug 20, 2007 (gmt 0)

10+ Year Member



Hi,

I cant seem to get it so that i dont get duplicate items - can anyone help - the code at present is:

<?php

define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
define('MAGPIE_DIR', 'magpie/');

require_once(MAGPIE_DIR.'rss_fetch.inc');

if ( isset($_GET['url']) ) {
$url = $_GET['url'];
}
else {
$url = 'http://www.example.com/rss/sportonline_uk_edition/front_page/rss.xml';
}

$rss = fetch_rss( $url );
//Change the number to change the number of items shown
$count = 3;

for ($i = 0; $i < $count; $i++)

{$items[] = $rss->items[rand(0, count($rss->items)-1)];}

if ($rss) {

foreach ($items as $item) {
$href = $item['link'];
$title = $item['title'];
$description = $item['description'];
echo "<p class='dark'>> <b><a class='dark' href=$href>$title</a></b><br />$description</p>";
}

}
else {
echo "Error: " . magpie_error();
}
?>

[edited by: dreamcatcher at 11:12 am (utc) on Aug. 20, 2007]
[edit reason] Use example.com, thanks. [/edit]

Habtom

10:50 am on Aug 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Right after the following line:
{$items[] = $rss->items[rand(0, count($rss->items)-1)];}

Add the following (this is not a solution, it is just to show you the content of that array, and is to be removed later)

echo "<pre>";
print_r($items);
echo "</pre>";

From what is printed, are there any duplicates?

Habtom

lj2007

11:01 am on Aug 20, 2007 (gmt 0)

10+ Year Member



Yeah there are, for example:

(
[0] => Array
(
[title] => Sunday's SPL photos
[description] => Pictures from Sunday's match in the SPL
[link] => http://www.example.com/go/rss/-/sport1/hi/scotland/6953904.stm
[guid] => http://www.example.com/sport1/hi/scotland/6953904.stm
[pubdate] => Sun, 19 Aug 2007 14:14:09 GMT
[category] => Scotland
[summary] => Pictures from Sunday's match in the SPL
[date_timestamp] => 1187532849
)

=> Array
(
[title] => Coulthard reveals bulimia battle
[description] => David Coulthard reveals how he suffered from an eating disorder in a bid to get into Formula One.
[link] => http://www.example.com/go/rss/-/sport1/hi/motorsport/formula_one/6954569.stm
[guid] => http://www.example.com/sport1/hi/motorsport/formula_one/6954569.stm
[pubdate] => Mon, 20 Aug 2007 09:27:55 GMT
[category] => Formula One
[summary] => David Coulthard reveals how he suffered from an eating disorder in a bid to get into Formula One.
[date_timestamp] => 1187602075
)

[2] => Array
(
[title] => Sunday's SPL photos
[description] => Pictures from Sunday's match in the SPL
[link] => http://www.example.com/go/rss/-/sport1/hi/scotland/6953904.stm
[guid] => http://www.example.com/sport1/hi/scotland/6953904.stm
[pubdate] => Sun, 19 Aug 2007 14:14:09 GMT
[category] => Scotland
[summary] => Pictures from Sunday's match in the SPL
[date_timestamp] => 1187532849
)

)

[1][edited by: dreamcatcher at 11:11 am (utc) on Aug. 20, 2007]
[edit reason] Use example.com, thanks. [/edit]

Habtom

11:11 am on Aug 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



My guess is the count($rss->items) is not outputing the correct number:
Can you remove the part I asked you to post before and replace it with
echo count($rss->items);
after the following line:
{$items[] = $rss->items[rand(0, count($rss->items)-1)];}
and see what is the number of rows you get.

Habtom

lj2007

11:20 am on Aug 20, 2007 (gmt 0)

10+ Year Member



15

Habtom

11:26 am on Aug 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I will give it a final shot :)

Change:
{$items[] = $rss->items[rand(0, count($rss->items)-1)];}

To:
{$items[$i] = $rss->items[rand(0, count($rss->items)-1)];}

lj2007

11:47 am on Aug 20, 2007 (gmt 0)

10+ Year Member



No, sorry still duplicates - very annoying!

Habtom

12:17 pm on Aug 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




{$items[] = $rss->items[rand(0, count($rss->items)-1)];}

if ($rss) {

foreach ($items as $item) {
$href = $item['link'];
$title = $item['title'];
$description = $item['description'];
echo "<p class='dark'>> <b><a class='dark' href=$href>$title</a></b><br />$description</p>";
}

Replace with the following:

{$items2[] = $rss->items[rand(0, count($rss->items)-1)];}

if ($rss) {

foreach ($items2 as $item) {
$href = $item['link'];
$title = $item['title'];
$description = $item['description'];
echo "<p class='dark'>> <b><a class='dark' href=$href>$title</a></b><br />$description</p>";
}

lj2007

12:30 pm on Aug 20, 2007 (gmt 0)

10+ Year Member



Nope still there....

pinterface

6:03 pm on Aug 20, 2007 (gmt 0)

10+ Year Member



From the page about array_rand [us2.php.net]:
If you are picking only one entry, array_rand() returns the key for a random entry. Otherwise, it returns an array of keys for the random entries.

Note how array_rand returns an array of keys, not an array of random elements. That means, rather than:

  $items = array_rand($rss->items, 3);
foreach ($items as $item) { /* use $item */ }
you want something more like:
  $item_keys = array_rand($rss->items, 3);
foreach ($item_keys as $key) {
$item = $rss->items[$key];
/* use $item */
}

Or (untested, but should give you the general idea):

  function array_rand_values($array, $num) {
if ($num == 1)
return $array[array_rand($array)];
else {
$ret = array();
foreach (array_rand($array, $num) as $key)
$ret[] = $array[$key];
return $ret;
}
}
...
$items = array_rand_values($rss->items, 3);
...

Or

shuffle($rss->items); $items = array_slice($rss->items, 0, 3);
, if you don't mind $rss->items getting reordered.

Incidentally, the reason

$items[] = $rss->items[rand(0, count($rss->items)-1)];
is giving you duplicate items is because that's how random numbers work. Each call to rand() picks a number independent of each prior call to rand, which means sometimes you'll get the same number twice in a row, just like sometimes you'll get "heads" thrice in a row when flipping a coin.

lj2007

9:45 am on Aug 21, 2007 (gmt 0)

10+ Year Member



Thanks so much - the shuffle solution makes much more sense!