二つの多次元配列を比較して、片方にだけ含まれるものを抽出する方法
- 評価
- クリップ 3
- VIEW 7,732
二つの多次元配列の片方にだけ含まれるものを抽出したいです。
具体的には、以下のような配列Aと配列Bを比べて、片方にだけ含まれる組み合わせ、すなわちこの場合は
[flag] => 88
[status] => 25
と
[flag] => 122
[status] => 25
の組み合わせが、最終的に得たい結果です。
配列A
Array
(
[0] => Array
(
[flag] => 2
[status] => 25
)
[1] => Array
(
[flag] => 64
[status] => 25
)
)
配列B
Array
(
[0] => Array
(
[flag] => 122
[status] => 25
)
[1] => Array
(
[flag] => 2
[status] => 25
)
[2] => Array
(
[flag] => 64
[status] => 25
)
[3] => Array
(
[flag] => 88
[status] => 25
)
)
試したコードは以下の通り。
<?php
//配列A
$ArrayA[] = array('flag'=>'2','status'=>'25');
$ArrayA[] = array('flag'=>'64','status'=>'25');
//配列B
$ArrayB[] = array('flag'=>'122','status'=>'25');
$ArrayB[] = array('flag'=>'2','status'=>'25');
$ArrayB[] = array('flag'=>'64','status'=>'25');
$ArrayB[] = array('flag'=>'88','status'=>'25');
foreach ($ArrayB as $key => $valarr) {
foreach ( $ArrayA as $key2 => $valarr2) {
$returnArray[] = array_diff_assoc($valarr, $valarr2);
}
}
echo "<pre>";
print_r($returnArray);
echo "</pre>";
差分をとるからdiffかなと思ったのですが、上記コードの実行結果は下記の通りで、意図とはだいぶ違いました。
Array
(
[0] => Array
(
[flag] => 122
)
[1] => Array
(
[flag] => 122
)
[2] => Array
(
)
[3] => Array
(
[flag] => 2
)
[4] => Array
(
[flag] => 88
)
[5] => Array
(
[flag] => 88
)
[6] => Array
(
[flag] => 64
)
[7] => Array
(
)
)
冒頭に挙げたようなflagとstatusの組み合わせを持つ要素だけを抽出するにはどうしたらいいでしょうか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+5
このように行ってみるのはいかがですか?
<?php
$arr1 = array(
array(
"flag" => 2,
"status" => 25
),
array(
"flag" => 64,
"status" => 25
)
);
$arr2 = array(
array(
"flag" => 122,
"status" => 25
),
array(
"flag" => 2,
"status" => 25
),
array(
"flag" => 64,
"status" => 25
),
array(
"flag" => 88,
"status" => 25
)
);
$array_diff = array_udiff($arr2, $arr1, function ($array1, $array2) {
$result1 = $array1['flag'] - $array2['flag'];
$result2 = $array1['status'] - $array2['status'];
return $result1 + $result2;
});
print_r($array_diff);
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+5
PHP7以降ならこう書くのが一番いいです。
<?php
$arr1 = [
['flag' => 2, 'status' => 25],
['flag' => 64, 'status' => 25],
];
$arr2 = [
['flag' => 122, 'status' => 25],
['flag' => 2, 'status' => 25],
['flag' => 88, 'status' => 25],
];
$compare = function ($x, $y) {
return $x['flag'] <=> $y['flag'] ?: $x['status'] <=> $y['status'];
};
var_dump(array_merge(
array_udiff($arr2, $arr1, $compare),
array_udiff($arr1, $arr2, $compare)
));
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
これでも一応。
//配列A
$ArrayA[] = array('flag'=>'2','status'=>'25');
$ArrayA[] = array('flag'=>'64','status'=>'25');
//配列B
$ArrayB[] = array('flag'=>'122','status'=>'25');
$ArrayB[] = array('flag'=>'2','status'=>'25');
$ArrayB[] = array('flag'=>'64','status'=>'25');
$ArrayB[] = array('flag'=>'88','status'=>'25');
$returnArray = array_filter( $ArrayB, function( $item ) use( $ArrayA ) {
$item = json_encode( $item );
foreach ( $ArrayA as $value ) {
if ( $item === json_encode( $value ) ) { return false; }
}
return true;
} );
echo "<pre>";
print_r($returnArray);
echo "</pre>";
/*
Array
(
[0] => Array
(
[flag] => 122
[status] => 25
)
[3] => Array
(
[flag] => 88
[status] => 25
)
)
*/
追記:
書き直しました。
$returnArray = array_filter( $ArrayB, function( $item ) use( $ArrayA ) {
foreach ( $ArrayA as $value ) {
if ( 0 === count( array_diff( $item, $value ) ) ) { return false; }
}
return true;
} );
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/08 00:00
試してみましたが、結果の配列は空でした。
Array
(
)
2017/01/08 00:24
2017/01/08 01:41
たしかに目的の結果が得られました!
しかし自分がアホなため、なぜこのコールバック関数で目的の結果が得られたのか、イマイチ原理というか挙動を理解できておりません。
もし出来ましたら、仕組みを解説をしていただけましたら幸いです。
2017/01/08 02:12
2017/01/08 02:21 編集
まだ自分の理解不足でよくわかっていないのですが、その方法ですとflagとstatusをそれぞれ別個に処理しているということですよね。でもそれだと、「flagとstatusの組み合わせ」が崩れたりしませんか?
たとえば質問文の例ではstatusが全て「25」なので問題にはなりませんが、もしstatusの値が全て異なっていた場合、「flagとstatusの組み合わせ」が維持されないような気が・・・
2017/01/08 02:25
でもどうしてあのコールバック関数でそのような挙動になるのか、自分の能力が低すぎて全然理解できません・・・
2017/01/08 12:05 編集
2017/01/09 01:47
たしかにそうですね。
ただ今回のケースでは要素に含まれるのは正の値のみなので、そういう点では問題ないかもしれません。