在保持顺序的同时将数组合并到正确的位置

时间:2014-01-09 08:43:12

标签: php arrays sorting array-merge

我有两个数组,都有一个position。我需要在正确的位置将它们合并在一起,同时保持每个数组中元素的顺序。

$array1 = array(
    array('name' => 'Bob', 'position' => 1),
    array('name' => 'Tim', 'position' => 1),
    array('name' => 'Alf', 'position' => 3),
    array('name' => 'Jon', 'position' => 3) 
);

$array2 = array(
    array('name' => 'Tom', 'position' => 2),
    array('name' => 'Joe', 'position' => 2),
    array('name' => 'Jim', 'position' => 2),
    array('name' => 'Kev', 'position' => 2)
);

我想要的输出是:

$output = array(
    array('name' => 'Bob', 'position' => 1),
    array('name' => 'Tim', 'position' => 1),
    array('name' => 'Tom', 'position' => 2),
    array('name' => 'Joe', 'position' => 2),
    array('name' => 'Jim', 'position' => 2),
    array('name' => 'Kev', 'position' => 2),
    array('name' => 'Alf', 'position' => 3),
    array('name' => 'Jon', 'position' => 3) 
);

我认为最好的方法是使用array_merge(),合并两个数组,然后使用简单的usort()根据它们的位置对它们进行排序。但是,当我这样做时,来自$array2的元素顺序不正确:

$output = array_merge($array1, $array2);

usort($output, function($a, $b) {
    return $a['position'] > $b['position'];
});

var_dump($output);

哪个输出:

$output = array(
    array('name' => 'Bob', 'position' => 1),
    array('name' => 'Tim', 'position' => 1),
    array('name' => 'Tom', 'position' => 2),
    array('name' => 'Joe', 'position' => 2),
    array('name' => 'Kev', 'position' => 2), // Should be 'name' => 'Jim'
    array('name' => 'Jim', 'position' => 2), // Should be 'name' => 'Kev'
    array('name' => 'Alf', 'position' => 3),
    array('name' => 'Jon', 'position' => 3) 
);

有没有办法解决这个问题,或者更好的方法来解决这个问题?

5 个答案:

答案 0 :(得分:0)

这有效,但它涉及触摸子数组,因此您必须确保不保留“缓存”键:

编辑:版本2

function position_merge(array $arr1,array $arr2)
{
    $result=array_merge($arr1,$arr2);
    array_walk($result,function(&$item,$idx){
        $item["array_index"]=$idx;// Make sure this key is not used
    });
    usort($result,function($a,$b){
        return $a["position"]-$b["position"]?:$a["array_index"]-$b["array_index"];
    });
    array_walk($result,function(&$item){
        unset($item["array_index"]);
    });
    return $result;
}

Online demo

print_r(position_merge($array1,$array2));将输出:

Array
(
    [0] => Array
        (
            [name] => Bob
            [position] => 1
        )

    [1] => Array
        (
            [name] => Tim
            [position] => 1
        )

    [2] => Array
        (
            [name] => Tom
            [position] => 2
        )

    [3] => Array
        (
            [name] => Joe
            [position] => 2
        )

    [4] => Array
        (
            [name] => Jim
            [position] => 2
        )

    [5] => Array
        (
            [name] => Kev
            [position] => 2
        )

    [6] => Array
        (
            [name] => Alf
            [position] => 3
        )

    [7] => Array
        (
            [name] => Jon
            [position] => 3
        )

)

旧版本1:

function position_merge(array $arr1,array $arr2)
{
    function addIndex(&$item,$idx)
    {
        $item["array_index"]=$idx;// Make sure this key is not used
    }
    function rmIndex(&$item)
    {
        unset($item["array_index"]);
    }
    array_walk($arr1,"addIndex");
    array_walk($arr2,"addIndex");
    $result=array_merge($arr1,$arr2);
    usort($result,function($a,$b){
        return $a["position"]>$b["position"]?1:($a["position"]<$b["position"]?-1:$a["array_index"]-$b["array_index"]);
    });
    array_walk($result,"rmIndex");
    return $result;
}

Online demo

答案 1 :(得分:0)

输出: http://codepad.org/K8pCY1yD

<强>代码:

<?php
$array1 = array(
    array('name' => 'Bob', 'position' => 1),
    array('name' => 'Tim', 'position' => 1),
    array('name' => 'Alf', 'position' => 3),
    array('name' => 'Jon', 'position' => 3)
);
$array2 = array(
    array('name' => 'Tom', 'position' => 2),
    array('name' => 'Joe', 'position' => 2),
    array('name' => 'Jim', 'position' => 2),
    array('name' => 'Kev', 'position' => 2)
);
$result = array_merge($array1, $array2);

$sorted = array();
foreach ($result as $key => $row) {
    $sorted[$key] = $row['position'];
}
array_multisort($sorted, $result);
?>
<pre>
<?php print_r($result); ?>
</pre>

答案 2 :(得分:0)

希望这有助于保留订单

 $arr =  array_merge($array1, $array2) ;
    $result=array();
    $len = sizeof($arr);
    for($i=0;$i<$len;$i++){
      $result[$arr[$i]['position']][] = $arr[$i];
    }
    ksort($result);
    $arr = array();
    foreach($result as $rs){
       $arr  = array_merge($arr,$rs); 
    }
    unset($result);
    print_r($arr);

答案 3 :(得分:0)

蛮力解决方案。除非你想复制,否则它会使数组指针混乱。

function merge (&$a, &$b)
{
    $c = array();
    $ea = reset ($a);
    $eb = reset ($b);
    do
    {
        if (!$ea) 
            { $c[]=$eb; $eb=next($b); }
        else if (!$eb) 
            { $c[]=$ea; $ea=next($a); }
        else if ($ea['position'] < $eb['position'])
            { $c[]=$ea; $ea=next($a); }
        else                                        
            { $c[]=$eb; $eb=next($b); }
    } while ($eb || $ea);
    return $c;
}

输出

array(8) {
  [0]=>
  array(2) {
    ["name"]=> string(3) "Bob"
    ["position"]=> int(1)
  }
  [1]=>
  array(2) {
    ["name"]=> string(3) "Tim"
    ["position"]=> int(1)
  }
  [2]=>
  array(2) {
    ["name"]=> string(3) "Tom"
    ["position"]=> int(2)
  }
  [3]=>
  array(2) {
    ["name"]=> string(3) "Joe"
    ["position"]=> int(2)
  }
  [4]=>
  array(2) {
    ["name"]=> string(3) "Jim"
    ["position"]=> int(2)
  }
  [5]=>
  array(2) {
    ["name"]=> string(3) "Kev"
    ["position"]=> int(2)
  }
  [6]=>
  array(2) {
    ["name"]=> string(3) "Alf"
    ["position"]=> int(3)
  }
  [7]=>
  array(2) {
    ["name"]=> string(3) "Jon"
    ["position"]=> int(3)
  }
}

答案 4 :(得分:0)

以下解决了我的问题,但它需要positions中的$array1按升序排序(就像它们在上面的代码中一样)。

$position = $array2[0]['position'];
foreach ($array1 as $key => $arr) {
    if ($position < $arr['position']) {
        $insertAtKey = $key;
        break;
    }
}
array_splice($array1, $insertAtKey, 0, $array2);