読者です 読者をやめる 読者になる 読者になる

HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

配列の統合時の先勝ち後勝ちの話

PHP

2つの配列$a$bをマージした結果として$expectedのようなものが欲しくて‥

<?php

$a = array(
            '11',
    'k2' => '22',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
);
$b = array(
            '111',
    'k2' => '222',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);
$expected = array (
            '111',
    'k2' => '222',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);

+演算子array_merge関数を使ってみるが‥

<?php

$a = array(
            '11',
    'k2' => '22',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
);
$b = array(
            '111',
    'k2' => '222',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);
$expected = array (
            '111',
    'k2' => '222',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);

printf("===%s===\n", 'expected');
var_dump($expected);
printf("===%s===\n", '$a + $b');
var_dump($a + $b);
printf("===%s===\n", '$b + $a');
var_dump($b + $a);
printf("===%s===\n", 'array_merge($a, $b)');
var_dump(array_merge($a, $b));
printf("===%s===\n", 'array_merge($b, $a)');
var_dump(array_merge($b, $a));

何かが違う‥

===expected===
array(8) {
  [0]=>
  string(3) "111"
  ["k2"]=>
  string(3) "222"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
}
===$a + $b===
array(8) {
  [0]=>
  string(2) "11"
  ["k2"]=>
  string(2) "22"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
}
===$b + $a===
array(8) {
  [0]=>
  string(3) "111"
  ["k2"]=>
  string(3) "222"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
}
===array_merge($a, $b)===
array(9) {
  [0]=>
  string(2) "11"
  ["k2"]=>
  string(3) "222"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
  [1]=>
  string(3) "111"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
}
===array_merge($b, $a)===
array(9) {
  [0]=>
  string(3) "111"
  ["k2"]=>
  string(2) "22"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
  [1]=>
  string(2) "11"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
}

まぁ$b + $aは、内容的には合っているんだけど、ベースは$aで後勝ちしたいのでちょっと違和感‥

array_mergeは惜しいが違うし‥

見た目の順番が同じものが得られないかな‥と思い、意味的にはこんな感じで、

<?php

$a = array(
            '11',
    'k2' => '22',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
);
$b = array(
            '111',
    'k2' => '222',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);

printf("===%s===\n", 'foreach');
$r = $a;
foreach ($b as $k => $v) {
    $r[$k] = $v;
}
var_dump($r);

こんな感じの結果が得られるやつ。

===foreach===
array(8) {
  [0]=>
  string(3) "111"
  ["k2"]=>
  string(3) "222"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
}

で、いろいろ試行錯誤して、

<?php

$a = array(
            '11',
    'k2' => '22',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
);
$b = array(
            '111',
    'k2' => '222',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);

printf("===%s===\n", 'array_merge(array_diff($a, array_intersect_key($a, $b)), $b)');
$r = array_merge(array_diff($a, array_intersect_key($a, $b)), $b);
var_dump($r);

で、見た目の順番は違うけど同じ結果が得られた。

array(8) {
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
  [0]=>
  string(3) "111"
  ["k2"]=>
  string(3) "222"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
}

‥と喜んでいたら、array_replaceなるものがあった件。

<?php

$a = array(
            '11',
    'k2' => '22',
    'k4' => '44',
    'k6' => '66',
    'k8' => '88',
);
$b = array(
            '111',
    'k2' => '222',
    'k3' => '333',
    'k5' => '555',
    'k7' => '777',
);

printf("===%s===\n", 'array_replace($a, $b)');
$r = array_replace($a, $b);
var_dump($r);

見た目の順番まで期待通り。

===array_replace($a, $b)===
array(8) {
  [0]=>
  string(3) "111"
  ["k2"]=>
  string(3) "222"
  ["k4"]=>
  string(2) "44"
  ["k6"]=>
  string(2) "66"
  ["k8"]=>
  string(2) "88"
  ["k3"]=>
  string(3) "333"
  ["k5"]=>
  string(3) "555"
  ["k7"]=>
  string(3) "777"
}

まとめ

私が知る限りの配列の「足し算」をする演算/関数の違いの簡単なまとめ。

演算/関数 数値インデックス 文字列インデックス
$a + $b 先勝ち 先勝ち
array_merge($a, $b) 続きから追記 後勝ち
array_replace($a, $b) 後勝ち 後勝ち

知らない事がまだまだ多いな‥