user3931836
user3931836

Reputation: 194

php Shuffle multi-dimensional array whilst maintaining column order

I have a multi-dimensional array as follows:

$lee[] = array("question" => "3", "appeared" => "0");
$lee[] = array("question" => "4", "appeared" => "1");
$lee[] = array("question" => "5", "appeared" => "0");
$lee[] = array("question" => "6", "appeared" => "0");
$lee[] = array("question" => "7", "appeared" => "1");
$lee[] = array("question" => "8", "appeared" => "1");
$lee[] = array("question" => "9", "appeared" => "2");
$lee[] = array("question" => "10", "appeared" => "0");
$lee[] = array("question" => "12", "appeared" => "3");
$lee[] = array("question" => "15", "appeared" => "3");
$lee[] = array("question" => "19", "appeared" => "3");


function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key=> $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}

array_sort_by_column($lee, 'appeared');

So far so good - now my array is sorted by the 'appeared' column in ascending order.

Now comes the problem. I want to randomly shuffle the array, but still maintaining the "appeared" column in ascending order

How can this be done? I have no clue..

Upvotes: 1

Views: 1132

Answers (3)

mickmackusa
mickmackusa

Reputation: 47883

It seems to me that these other answers are over-engineered (no wonder you can't follow what they do). You only need two function calls, shuffle() then usort(). There is no need to group them at all. (I'm going use the "spaceship" operator in my demo, but you can use any of the old-school comparison techniques if your php version requires it.)

Code: (Demo)

shuffle($lee);  // shuffle the array
usort($lee,function($a,$b){return $a['appeared']<=>$b['appeared'];});  // sort shuffled array by appeared value
var_export($lee);

Possible Output:

array (
  0 => 
  array (
    'question' => '10',
    'appeared' => '0',
  ),
  1 => 
  array (
    'question' => '5',
    'appeared' => '0',
  ),
  2 => 
  array (
    'question' => '6',
    'appeared' => '0',
  ),
  3 => 
  array (
    'question' => '3',
    'appeared' => '0',
  ),
  4 => 
  array (
    'question' => '4',
    'appeared' => '1',
  ),
  5 => 
  array (
    'question' => '8',
    'appeared' => '1',
  ),
  6 => 
  array (
    'question' => '7',
    'appeared' => '1',
  ),
  7 => 
  array (
    'question' => '9',
    'appeared' => '2',
  ),
  8 => 
  array (
    'question' => '12',
    'appeared' => '3',
  ),
  9 => 
  array (
    'question' => '15',
    'appeared' => '3',
  ),
  10 => 
  array (
    'question' => '19',
    'appeared' => '3',
  ),
)

p.s. Ordering by appeared DESC is as simple as swapping $a and $b after return.

Upvotes: 1

Gyandeep Sharma
Gyandeep Sharma

Reputation: 2327

<?php
    $lee[] = array("question" => "3", "appeared" => "0");
    $lee[] = array("question" => "4", "appeared" => "1");
    $lee[] = array("question" => "5", "appeared" => "0");
    $lee[] = array("question" => "6", "appeared" => "0");
    $lee[] = array("question" => "7", "appeared" => "1");
    $lee[] = array("question" => "8", "appeared" => "1");
    $lee[] = array("question" => "9", "appeared" => "2");
    $lee[] = array("question" => "10", "appeared" => "0");
    $lee[] = array("question" => "12", "appeared" => "3");
    $lee[] = array("question" => "15", "appeared" => "3");
    $lee[] = array("question" => "19", "appeared" => "3");

    function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
        $sort_col = array();
        foreach ($arr as $key=> $row) {
            $sort_col[$key] = $row[$col];
        }

        array_multisort($sort_col, $dir, $arr);
    }
    array_sort_by_column($lee, 'appeared');
    foreach( $lee as $row){
        $question[] = $row['question'];
    }
    shuffle($question);

    for($i=0;$i<count($lee);$i++){
        $lee[$i]['question'] = $question[$i];
    }
    echo "<pre>";print_r($lee);

Upvotes: 0

u_mulder
u_mulder

Reputation: 54831

$lee[] = array("question" => "3", "appeared" => "0");
$lee[] = array("question" => "4", "appeared" => "1");
$lee[] = array("question" => "5", "appeared" => "0");
$lee[] = array("question" => "6", "appeared" => "0");
$lee[] = array("question" => "7", "appeared" => "1");
$lee[] = array("question" => "8", "appeared" => "1");
$lee[] = array("question" => "9", "appeared" => "2");
$lee[] = array("question" => "10", "appeared" => "0");
$lee[] = array("question" => "12", "appeared" => "3");
$lee[] = array("question" => "15", "appeared" => "3");
$lee[] = array("question" => "19", "appeared" => "3");

$parts = [];
// Group items by `appeared` value
foreach ($lee as $item) {
    $parts[$item['appeared']][] = $item;
}

// shuffle each group
foreach ($parts as &$part) {
    shuffle($part);
}

// sort array by keys in ascending order
ksort($parts);
// merge groups to one array
print_r(call_user_func_array('array_merge', $parts));

Upvotes: 1

Related Questions