简体   繁体   中英

Get array element with sub elements without repeating in PHP

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

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 .

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

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 )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM