Reputation: 11
I walk around here with some hesitation, I have passed an array with sub elements (so to speak) and I need three random values but these are obtained without repeating.
The array is as follows:
Array ( [0] => Array ( [uid] => 1 [ticket_code] => 0oreb8yo ) [1] => Array ( [uid] => 1 [ticket_code] => 2oeii8hm ) [2] => Array ( [uid] => 1 [ticket_code] => m0dwtjiw ) [3] => Array ( [uid] => 1 [ticket_code] => q6c7cymb ) [4] => Array ( [uid] => 1 [ticket_code] => zyqhm5bj ) [5] => Array ( [uid] => 1 [ticket_code] => amdqzjpi ) [6] => Array ( [uid] => 2 [ticket_code] => tzql7l42 ) [7] => Array ( [uid] => 2 [ticket_code] => gap0r6vf ) [8] => Array ( [uid] => 2 [ticket_code] => ypqum5yz ) [9] => Array ( [uid] => 4 [ticket_code] => smupluac ) [10] => Array ( [uid] => 4 [ticket_code] => 9d8jsha7 ) [11] => Array ( [uid] => 5 [ticket_code] => 6hdnja42 ) )
And I need you to get 3 "ticket_code" but no right to repeat the "uid".
I've been on trying as follows, but also repeats the "uid".
$ticketsWinners = array();
for ($i=0; $i < 3; $i++) {
$aux = array_rand($allTickets);
$aux2 = $allTickets[$aux]['uid'];
$ticketsWinners[] = array(
'uid' => $aux2,
'ticket_code' => $allTickets[$aux]['ticket_code']
);
}
Any way to do it without repeats?
We thank you in advance if anyone knows of something ^^
Upvotes: 1
Views: 85
Reputation: 21671
this structure would be better ( added benefit of ticket numbers being unique )
$tickets = Array
(
'0oreb8yo' => 1,
'2oeii8hm' => 1,
'm0dwtjiw' => 1,
'q6c7cymb' => 1,
'zyqhm5bj' => 1,
'amdqzjpi' => 1,
'tzql7l42' => 2,
'gap0r6vf' => 2,
'ypqum5yz' => 2,
'smupluac' => 3,
'9d8jsha7' => 4,
'6hdnja42' => 5,
);
$winners = array();
$picks = 3;
for($i = 0; $i < $picks; $i++){
if(count($tickets) == 0 ){
break; //or error -- shouldn't need this unless picks exceed uids
}
$ticket = array_rand($tickets);
$winner = $tickets[$ticket];
$winners[] = $winner;
$tickets = array_filter($tickets, function($item) use ($winner){
return $winner != $item;
});
}
echo '<pre>';
var_export($winners);
outputs
array (
0 => 2,
1 => 1,
2 => 4,
)
array (
0 => 2,
1 => 1,
2 => 3,
)
array (
0 => 1,
1 => 3,
2 => 2,
)
unlike the while option, this will reduce the operations for each loop of the for loop by reducing the ticket array by the uid. It's also the only way to insure your not always pulling out a user with tickets, what if user 1 bought 90% of the tickets, you'd loop on him 90% of the time, in any case you have to reduce the ticket array by winners if they can win only once. In essence you remove each uid from the list when they win. You can also be sure that each ticket has the same chance to win ( as well as array_rand is random that is ) - they all have equal footing.
ticket array reduction after loop1
array (
'tzql7l42' => 2,
'gap0r6vf' => 2,
'ypqum5yz' => 2,
'smupluac' => 3,
'9d8jsha7' => 4,
'6hdnja42' => 5,
)
after loop2
array (
'smupluac' => 3,
'9d8jsha7' => 4,
'6hdnja42' => 5,
)
after loop3
array (
'smupluac' => 3,
'6hdnja42' => 5,
)
winners
array (
0 => 1,
1 => 2,
2 => 4,
)
to return both the uid and wining ticket change
$winners[] = $winner;
to
$winners[$ticket] = $tickets[$ticket];
now winners will be, just like the input array
ticketnumber => uid
ticket is the key ( which is the ticket ) and winner is the value ( which is the uid )
Upvotes: 0
Reputation: 54831
Try something like:
$ticketsWinners = array();
while (sizeof($ticketsWinners) < 3) {
$aux = array_rand($allTickets);
// array_rand return array of keys so you need first value only
$uid = $allTickets[$aux[0]]['uid']
// add uid as a key so ass not tot check all $allTickets values
if (!isset($ticketsWinners[$uid]))
$ticketsWinners[$uid] = $allTickets[$aux[0]];
}
// if you need $allTickets back to numeric keys [0, 1, 2]
$allTickets = array_values($allTickets);
if you're afraid of infinite loops (that can take place really) then try this:
$ticketsWinners = array();
// shuffle array before checking
shuffle($allTickets);
foreach ($allTickets as $tick_data) {
$uid = $tick_data['uid'];
if (!isset($ticketsWinners[$uid]))
$ticketsWinners[$uid] = $tick_data;
if (sizeof($ticketsWinners) == 3)
break;
}
Here in worst case you check $allTickets
array and get winners of size <= 3
.
Upvotes: 1
Reputation: 3986
Try this:
$ticketsWinners = array();
$ticketUid = array();
for ($i=0; $i < 3; $i++) {
$aux = array_rand($allTickets);
$aux2 = $allTickets[$aux]['uid'];
if(! in_array($aux2, $ticketUid)) {
$ticketUid[$i] = $aux2;
$ticketsWinners[] = array(
'uid' => $aux2,
'ticket_code' => $allTickets[$aux]['ticket_code']
);
} else {
$i--;
}
}
Upvotes: 0