質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

250閲覧

PHPで配列を連結するとき、条件分岐がうまくできない

love_kinniky

総合スコア22

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2019/05/21 10:47

###実現したいこと
後述する「該当の配列($base_arr$new_arr)」を条件に従って連結し、次の$update_arrを作りたいです。

php

1$update_arr = array( 2 array( 3 'time' => ['1558432388750'], 4 'action' => 'lose', 5 'target_id' => '76', 6 'actor_id' => ['87'], 7 'type' => 'a', 8 ), 9 array( 10 'time' => [0000000000000,'1558432437780','1558432449937'], // 連結した結果こうなる 11 'action' => 'get', 12 'target_id' => '10', 13 'actor_id' => ['3','9','51'], // 連結した結果こうなる 14 'type' => 'a', // ここは a になる 15 ) 16);

###該当の配列
こちらが素材となる配列です。

php

1/* 2$base_arr 3元からある、0個以上の配列(今回は2つ) 4*/ 5$base_arr = array( 6 array( 7 'time' => ['1558432388750'], 8 'action' => 'lose', 9 'target_id' => '76', 10 'actor_id' => ['87'], 11 'type' => 'a', 12 ), 13 array( 14 'time' => ['1558432437780','1558432449937'], 15 'action' => 'get', 16 'target_id' => '10', 17 'actor_id' => ['9','51'], 18 'type' => 'b', 19 ) 20); 21 22/* 23$new_arr 24新しく連結される配列で、常に1つ 25*/ 26$time_ux = ceil(microtime(true)*1000); 27$new_arr = array( 28 array( 29 'time' => [$time_ux], 30 'action' => 'get', 31 'target_id' => '10', 32 'actor_id' => ['3'], 33 'type' => 'a', 34 ) 35); 36

連結の条件としては、

➀ ``$base_arr`` のどれかの ``'action'`` が、``$new_arr`` の ``'action'`` と同じであること。 ➁ ``$base_arr`` のどれかの ``'target_id'`` が、``$new_arr`` の ``'target_id'`` と同じであること。 この➀➁を両方とも満たした場合に配列を連結したい。という感じで、その結果が冒頭の「実現したいこと」にある``$update_arr``となります。

###発生している問題
下記の「試したこと」にあるコードで挑戦してみました。

ですが、$base_arr'lose'の配列にまで$new_arrが連結されてしまうという状況です。

$new_arr'action''get'なのに、なぜ'lose'の方にまで連結されてしまうのでしょうか。

###試したこと
こちらが問題の発生するコードです。

php

1 2// 素材となる配列 3$base_arr = get_base_arr(); 4$new_arr = get_new_arr(); 5 6// $base_arr がない場合 7if( empty($base_arr) || is_null($base_arr) ){ 8 $update_arr = $new_arr; 9} 10 11// すでに $base_arr がある場合 12else{ 13 foreach ( $base_arr as $base_keys ){ 14 if( $base_keys['action'] == $new_arr[0]['action'] && $base_keys['target_id'] == $new_arr[0]['target_id'] ){ 15 for( $i = 0; $i < count($base_arr); $i++ ) { 16 $base_arr[$i]['time'] = array_slice( array_merge($new_arr[0]['time'], $base_arr[$i]['time']), 0, 20 ); 17 $base_arr[$i]['actor_id'] = array_slice( array_merge($new_arr[0]['actor_id'], $base_arr[$i]['actor_id']), 0, 20 ); 18 $base_arr[$i]['type'] = 'a'; 19 } 20 } 21 $update_arr = $base_arr; 22} 23 24// 確認 25var_export($update_arr); 26

サンプルをご用意いたしましたので、ご確認頂ければと思います。
https://3v4l.org/TXjQc

宜しくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

条件に一致した場合、for文がまわっちゃってるので全部を連結対象にしてしまってますね。

else部分を書きみたく書き換えれば良さそうですかね。

foreach ( $base_arr as $i => $base_keys ){ if( $base_keys['action'] == $new_arr[0]['action'] && $base_keys['target_id'] == $new_arr[0]['target_id'] ){ $base_arr[$i]['time'] = array_slice( array_merge($new_arr[0]['time'], $base_arr[$i]['time']), 0, 20 ); $base_arr[$i]['actor_id'] = array_slice( array_merge($new_arr[0]['actor_id'], $base_arr[$i]['actor_id']), 0, 20 ); $base_arr[$i]['type'] = 'a'; } }

投稿2019/05/21 11:14

Eggpan

総合スコア2665

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

love_kinniky

2019/05/21 11:24

なるほどー!ありがとうございます。あとこれはそもそも質問の時点でもそうなんですけど、時間のところに小数点が1つ入るのって、なんだと思われますか?「1558437751001.0」のように、「.0」とかいうのが…
Eggpan

2019/05/21 12:08

ceil関数の戻り値がfloat型だからかと思います。 見た感じだと文字列で扱いたいみたいなので、 $time_ux = ceil(microtime(true)*1000); を $time_ux = strval(ceil(microtime(true)*1000)); とすれば他の配列と同じような形になるとおもいます。 var_export((float)1); が1.0と表示されるのは、 intとfloatが見分けつくようにそんな仕様になってるのかなと思ってますが、正確な所はちょっとわからないです。 プログラム書く時は違う型なので意識はしてますけども。(floatとかの少数型は丸め誤差、というのがよくあるので)
love_kinniky

2019/05/21 12:20

ありがとうございます。そもそもなんで文字列で扱いたいのか特に理由がなかったので笑、intvalにしてみました。(普通数字を扱うときわざわざ文字列にしませんよね?)
Eggpan

2019/05/21 12:35

桁数次第かと思います。64bitなら単位でいうと京まで扱えるので、現状の入れ方なら数値でいいとおもいます。
love_kinniky

2019/05/21 12:56

考えたことありませんでした。最後までありがとうございました。
guest

0

こんな感じですか?

PHP

1$base_arr = array( 2 array( 3 'time' => ['1558432388750'], 4 'action' => 'lose', 5 'target_id' => '76', 6 'actor_id' => ['87'], 7 'type' => 'a', 8 ), 9 array( 10 'time' => ['1558432437780','1558432449937'], 11 'action' => 'get', 12 'target_id' => '10', 13 'actor_id' => ['9','51'], 14 'type' => 'b', 15 ) 16); 17$time_ux = ceil(microtime(true)*1000); 18$new_arr = array( 19 array( 20 'time' => [$time_ux], 21 'action' => 'get', 22 'target_id' => '10', 23 'actor_id' => ['3'], 24 'type' => 'a', 25 ) 26); 27$update_arr=array_map(function($x) use ($new_arr){ 28 if($x["target_id"]==$new_arr[0]["target_id"] and 29 $x["action"]==$new_arr[0]["action"]){ 30 array_push($x["time"],$new_arr[0]["time"][0]); 31 array_push($x["actor_id"],$new_arr[0]["actor_id"][0]); 32 $x["type"]=$new_arr[0]["type"]; 33 } 34 return $x; 35},$base_arr); 36print_r($update_arr);

投稿2019/05/21 11:07

編集2019/05/21 11:07
yambejp

総合スコア114572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2019/05/21 11:09

target_idとactionがどれにも合致しなかったときに 合体せずに新規で配列が増えるのでしょうか? いまのとこ無視しています
love_kinniky

2019/05/21 11:26 編集

ほぼイメージ通りです。useとかレベル高くてわからないですけどw、どうもありがとうございます。 でも、new_arrのactor_idとtimeは先頭に連結したいというのがあります。 ご回答のactor_idは「9-51-3」の順になっていますが、「3-9-51」を実現したいと考えていました。 >target_idとactionがどれにも合致しなかったとき はい、そうです。合致しなければ新しい配列が増えます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問