views:

168

answers:

3

I know I'm doing this a bad way... but I'm having trouble seeing any alternatives. I have an array of products that I need to select 4 of randomly. $rawUpsellList is an array of all of the possible upsells based off of the items in their cart. Each value is a product object. I know this is horribly ugly code but I don't see an alternative now.... someone please put me out of my misery so this code doesn't make it to production.....

$rawUpsellList = array();
foreach ($tru->global->cart->getItemList() as $item) {
    $product = $item->getProduct();

    $rawUpsellList = array_merge($rawUpsellList, $product->getUpsellList());
}

$upsellCount = count($rawUpsellList);

$showItems = 4;
if ($upsellCount < $showItems) {
    $showItems = $upsellCount;
}

$maxLoop = 20;
$upsellList = array();
for ($x = 0; $x <= $showItems; $x++) {
    $key = rand(0, $upsellCount);
    if (!array_key_exists($key, $upsellList) && is_object($rawUpsellList[$key])) {
        $upsellList[$key] = $rawUpsellList[$key];           
        $x++;
    }

    if ($x == $maxLoop) {
        break;
    }
}

Posting this code was highly embarassing...

+6  A: 

Actually, pulling randomly from an array is a tough nut to crack - even Microsoft had trouble recently. That's a decent code sample for someone who I assume isn't an expert in algorithms, but also may be statistically skewed. As I said, it's difficult to do this right.

Thankfully, PHP already has the function array_rand, which seems to do what you want: return N items randomly chosen from an array. Is that what you're looking for?

$upsellList = array_rand($rawUpsellList, 4);
Matchu
+1  A: 

array_rand will let you pick one or more elements randomly from an array.

To use it (and save yourself a lot of headache), simply do something like

$upsellList = array_rand($rawUpsellList, 4);
Sebastian P.
+2  A: 

I am not really into PHP, but as an algorithm I will consider this pseudocode or whatever:

List<WhateverTypeYouWant> array;
List<WhateverTypeYouWant> selectedElements;

for (int i = 1; i <= 4; i++)
{
   int randomIndex = random(array.size());
   selectedElements.add(array[randomIndex]);
   array.remove(randomIndex);
}
Petar Minchev
This is a basic implementation of the [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle) :)
Matchu
Hah, thanks:) I didn't know that it has a name, though I have used it many times.
Petar Minchev
...I also just noticed that Markdown somehow broke the URL. http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
Matchu
This doesn't work because It will stop after only 4 loops, I need it not to stop after 4 loops but not stop till there are 4 random products selected.
Webnet
But on every iteration of the loop a new element is selected. What do you mean?
Petar Minchev
It doesn't return the array he's removing from. He finds an element, adds it to *another* array, and removes it from the original.
Matchu
@Webnet Didn't you notice the "array.remove(randomIndex)" line?
Petar Minchev
@Petar: I think he's thinking that you will keep removing elements until you have 4 left.
Matchu