1

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 ^^

5
  • whats the source of the data? Commented Jul 6, 2014 at 6:27
  • can you restructure the input array? it would be easier to index by the uid as the key, then array_suffle, unset( uid ) Commented Jul 6, 2014 at 6:31
  • ^never mind that will un-biased the output, ie. the more tickets purchased the greater the chance of winning should be but only win once maybe the other way, tickets as the the key with users as the data, then array filter with the user id when they win to remove them. Commented Jul 6, 2014 at 6:36
  • As you mention ArtisiticPhoenix is a raffle system. How could I be so if the array is restructured? Commented Jul 6, 2014 at 6:40
  • see my answer, and explanation, if you plan to sell a lot of tickets, you will need to reduce the complexity as you remove uids not increase it. Commented Jul 6, 2014 at 7:17

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but I only generates an infinite loop. You know something else like to do?
Added another solution
0

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--;
    }
}

2 Comments

how many tickets are you selling? to how many people? any idea.
for each ticket you sell you may be adding winners*tickets loops to the operation, so for a small example as this it may be fine but if you sell 10,000 tickets to 100 uids, you could do 100 x previous winners loops assuming each user got 100 tickets, each time a winner is picked. -- had a few extra 0's in there
0

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 )

2 Comments

Ok, this works, but it happens that not only need the "uid", but also "ticket_code" as would be checking in that case? What would be the best way to do this? I Speak seeing it on the side of site optimization.
so you need to have returned both the uid and ticket that won, that's easy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.