0

I want to merge / mix two arrays together, but I want it to be randomly "mixed" however NOT shuffled. For example:

$first = [1, 2, 3, 4];
$second = [10, 20, 30, 40];

Possible desired "mixes" are:

  • [1, 10, 20, 30, 2, 40, 3, 4]
  • [10, 1, 2, 20, 30, 3, 4, 40]
  • [1, 2, 3, 10, 20, 4, 30, 40]

Note that if we pluck the values back out we would still have the original orders of:

1, 2, 3, 4
10, 20, 30, 40
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Rob
  • 10,851
  • 21
  • 69
  • 109
  • I wonder ain't it better to make an associative array of these two (with `array_combine`). – raina77ow Nov 12 '13 at 10:24
  • Can you define `randomly "mixed"` and `shuffle` ? – Shankar Narayana Damodaran Nov 12 '13 at 11:49
  • Somewhat related: [Insert elements from one array (one-at-a-time) after every second element of another array (un-even zippering)](https://stackoverflow.com/q/12520272/2943403) and [Interleaving multiple arrays into a single array](https://stackoverflow.com/q/1860490/2943403) – mickmackusa Sep 06 '22 at 22:43

5 Answers5

0

Loop this script until both arrays are done.

$j = 0;
$i = 0;
$r = rand(0, 1);

if($r == 0) {
    $ret .= $array1[$i];
    $i++;
} elseif($r == 1) {
    $ret .= $array2[$j];
    $j++;
}

Of course, you have to handle a few exceptions in this code, but it might be the route.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Realitätsverlust
  • 3,941
  • 2
  • 22
  • 46
0

Well, there's (yet another) one possible approach:

$arr = call_user_func_array('array_merge', array_map(null, $first, $second));
print_r($arr); // [1, 10, 2, 20, 3, 30, 4, 40];

Demo. That's apparently deterministic; for random ordering each pair should be shuffled additionally. For example:

function zipShuffle($first, $second) {
  return call_user_func_array('array_merge', array_map(function($a, $b) {
    return mt_rand(0, 1) ? [$a, $b] : [$b, $a];
  }, $first, $second));
}

... but that obviously won't be able to churn out something like [1,2,3,10,20...]. If this is required, here's another solution:

function orderedShuffle($first, $second) {
  $results = [];
  $stor    = [$first, $second];
  $i       = mt_rand(0, 1);
  // switching between arrays on the fly
  while (list(, $v) = each($stor[$i])) {
    $results[] = $v;
    $i = mt_rand(0, 1);
  }

  // one array is gone, now we need to add all the elements
  // of the other one (as its counter left where it was)
  $i = 1 - $i;
  while (list(, $v) = each($stor[$i])) {
    $results[] = $v;
  }
  return $results;
}

Demo. The last function is actually quite easy to extend for as many arrays as required.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
0

Can you try this,

    <?php 


        $first = array(1,2,3,4);
        $second = array(10,20,30,40);

        $arrayMixed=array();
        $firstReverse=array_reverse($first);
        $secondReverse=array_reverse($second);

        $firstReverseCount = count($firstReverse);
        $secondReverseCount = count($secondReverse);

        foreach($firstReverse as $key=>$val) {
            if ($firstReverseCount>0) { 

                    array_push($arrayMixed, array_pop($firstReverse));

                    if ($secondReverseCount>0) {
                        array_push($arrayMixed, array_pop($secondReverse));
                    }

            }
        }
        $ArrayMixeddata =  array_merge($arrayMixed, $second);       


        echo "<pre>";
            print_r($ArrayMixeddata);
        echo "</pre>";
?>
Krish R
  • 22,583
  • 7
  • 50
  • 59
0

Not quick ways, but them works.

    // with permutations
    function combineShuffleOrder($first, $second)
    {
        // combine into one array with alternation
        $firstLen = count($first);
        $secondLen = count($second);
        $max = max($firstLen, $secondLen);
        $result = array();
        for($i=0; $i < $max; $i++) {
            if ($i < $firstLen)
                $result[] = $first[$i];
            if ($i < $secondLen)
                $result[] = $second[$i];
        }

        // "shuffle" with permutation
        $len = count($result);
        for($i=1; $i<$len; $i++) {
            if (rand(1, 3) % 2 == 0) {
                $tmp = $result[$i-1];
                $result[$i-1] = $result[$i];
                $result[$i] = $tmp;
                $i++; // skip one exchange
            }
        }
        return $result;
    }

    // with using "shuffle" in subarray 
    function combineShuffleOrder2($first, $second)
    {
        // combine into one array with alternation
        $firstLen = count($first);
        $secondLen = count($second);
        $max = max($firstLen, $secondLen);
        $result = array();
        for($i=0; $i < $max; $i++) {
            $sub = array();
            if ($i < $firstLen)
                $sub[] = $first[$i];
            if ($i < $secondLen)
                $sub[] = $second[$i];
            shuffle($sub);
            $result = array_merge($result, $sub);
        }

        return $result;
    }

    // with using "shuffle" in subarray if sources arrays are equals by length
    function combineShuffleOrder3($first, $second)
    {
        $max = count($first);
        $result = array();
        for($i=0; $i < $max; $i++) {
            $sub = array(
                $first[$i],
                $second[$i]
            );
            shuffle($sub);
            $result = array_merge($result, $sub);
        }

        return $result;
    }

    $first = array(1,2,3,4);
    $second = array(10,20,30,40);
    print_r(combineShuffleOrder($first, $second));
    print_r(combineShuffleOrder2($first, $second));
    print_r(combineShuffleOrder3($first, $second));
Alexander
  • 807
  • 5
  • 10
0

I recommend forming a single array of the two input arrays for simpler toggling. Simply loop and consume one element from a randomly selected array and push that selection into the result array. When the pool of arrays is reduced to a single array, kill the loop and append the remaining elements of the last surviving array onto the result array.

I'll use a pool of four arrays (one which is empty from the beginning) to demonstrate that the snippet is robust enough to handle a variable number of arrays, a variable number of elements in each array, and empty arrays.

Code: (Demo)

$first = [1, 2, 3, 4];
$second = [10, 20, 30, 40];
$third = [];
$fourth = ['a', 'b'];

$pool = [$first, $second, $third, $fourth];
$result = [];
while (count($pool) > 1) {
    $pullFrom = array_rand($pool);
    if (!$pool[$pullFrom]) {
        unset($pool[$pullFrom]);
        continue;
    }
    $result[] = array_shift($pool[$pullFrom]);
}
var_export(array_merge($result, ...$pool));

Alternatively without array_merge() and count() calls, but it makes more iterated calls of array_shift(): (Demo)

$pool = [$first, $second, $third, $fourth];
$result = [];
while ($pool) {
    $pullFrom = array_rand($pool);
    if (!$pool[$pullFrom]) {
        unset($pool[$pullFrom]);
        continue;
    }
    $result[] = array_shift($pool[$pullFrom]);
}
var_export($result);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136