Shuffle the order of keys in an associative array if they have the same value?

Given such an associative array, how can you shuffle the order of keys having the same value?

array(a => 1,
      b => 2,  // make b or c ordered first, randomly
      c => 2,
      d => 4,
      e => 5,  // make e or f ordered first, randomly
      f => 5);

The approach I tried was to turn it into such a structure and shuffle the values โ€‹โ€‹(which are arrays of source keys), and then roll it back to its original form. Is there a simpler or cleaner approach? (I'm not worried about performance; this is for small data sets.)

array(1 => [a],
      2 => [b, c],  // shuffle these
      4 => [d], 
      5 => [e, f]); // shuffle these


function array_sort_randomize_equal_values($array) {
    $collect_by_value = array();
    foreach ($array as $key => $value) {
        if (! array_key_exists($value, $collect_by_value)) {
            $collect_by_value[$value] = array();
        }
        // note the &, we want to modify the array, not get a copy
        $subarray = &$collect_by_value[$value];
        array_push($subarray, $key);
    }

    arsort($collect_by_value);

    $reordered = array();
    foreach ($collect_by_value as $value => $array_of_keys) {
        // after randomizing keys with the same value, create a new array
        shuffle($array_of_keys);
        foreach ($array_of_keys as $key) {
            array_push($reordered, $value);
        }
    }

    return $reordered;
}
+4
source share
2 answers

, , ( . ):

  •   (100 000 ): ร˜ 4.4 .
  • (100 000 ): ร˜ 1,3 .

array_flip(), , . $result $keyPool .

, array_keys() $keyPool . shuffle() , :

foreach($uniqueValues as $value => $notNeeded){
    $keyPool[$value] = array_keys($arr, $value, TRUE);
    shuffle($keyPool[$value]);
}

array_shift() $keyPool $result:

foreach($arr as $value)
    $result[array_shift($keyPool[$value])] = $value;

, , array_shift(), .

<?php

    $arr = ["a" => 1, "b" => 1, "c" => 1, "d" => 1, "e" => 1, "f" => 2,
            "g" => 1, "h" => 3, "i" => 4, "j" => 5, "k" => 5];


    function randomize_duplicate_array_value_keys(array $arr){

        $uniqueValues = array_flip($arr);
        $result = [];
        $keyPool = [];

        foreach($uniqueValues as $value => $notNeeded){
            $keyPool[$value] = array_keys($arr, $value, TRUE);
            shuffle($keyPool[$value]);
        }

        foreach($arr as $value)
            $result[array_shift($keyPool[$value])] = $value;

        return $result;

    }


    $result = randomize_duplicate_array_value_keys($arr);
    print_r($result);

?>

():

Array (
    [b] => 1
    [g] => 1
    [a] => 1
    [e] => 1
    [d] => 1
    [f] => 2
    [c] => 1
    [h] => 3
    [i] => 4
    [k] => 5
    [j] => 5
)

  • array_flip() array_unique(), , .

  • if, , , if . , , :

    if(count($keyPool[$value]) > 1)
        shuffle($keyPool[$value]);
    
  • , :

    • , ,

      function randomize_duplicate_array_value_keys(array $arr){
       
          if(empty($arr))
              return [];
       
          $uniqueValues = array_flip($arr);
          $result = [];
          //***
      }
    • , :

      function randomize_duplicate_array_value_keys(array $arr){
       
          if(empty($arr))
              return [];
          elseif(empty(array_filter(array_count_values($arr), function($v){return $v > 1;})))
              return [];
       
          $uniqueValues = array_flip($arr);
          $result = [];
          //***
      }
+5

, , . , , . , rand(0,1) , , :

<?php

$l = ['a' => 1,'b' => 2, 'c' => 2,
    'd' => 4,'e' => 5,'f' => 5];

asort($l);
$prevK = key($l);
$prevV = array_shift($l); //initialize prev to 1st element    
$shuffled = [];

foreach($l as $k => $v) {
    if($v != $prevV || rand(0,1)) {
        $shuffled[$prevK] = $prevV;
        $prevK = $k;
        $prevV = $v;
    }
    else {
        $shuffled[$k] = $v;
    }
}

$shuffled[$prevK] = $prevV;

print_r($shuffled);
+1

All Articles