I'm building a gift exchange website, where people put in their emails, and then each of the entrants is matched with another entrant (the sender). I'm using PHP (probably Symfony, if it makes a difference).
I'm expecting the number of entrants to be around 600-800, and this will be run quite frequently.
I thought I could use shuffle()
and array_combine()
on the array of recipients to do this.
However, after the shuffle()
the sender could still be in the same position, so would have to give a Secret Santa present to themselves.
For example:
$recipients = "SQL query that returns array"
# ['bob', 'alice', 'joe']
$senders = $recipients;
shuffle($senders);
# ['alice', 'bob', 'joe']
$result = array_combine($recipients, $senders);
# ['bob' => 'alice', 'alice' = 'bob', 'joe' => 'joe']
So I need to guarantee that in the final array, none of the values equal the key. So far, I have thought of the following possible solutions but they all seem expensive and a bit rubbish:
- Use
array_walk()
over the final array. Put any values into another array, then swap them with each other afterwards. If there's only 1, just swap it with anything. - Take all the values from the
$recipients
array that have even keys, and all the values from the$senders
array that have odd keys. Shuffle both of those arrays. - Instead of using
shuffle()
implement my own crappy version that does something like shift all the values forward two, and then doarray_reverse()
. - Loop through recipients, and use
array_rand()
to pick an item from$senders
. If it's the same, pick again, otherwise remove it from the array, set it the be the sender for that recipient, and move on to the next recipient.
Perhaps I'm overthinking this - is there a simpler way? Or is there a special way of doing this in PHP that I don't know about?