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

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

ただいまの
回答率

87.93%

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 392

score 22

実現したいこと

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

$update_arr = array(
    array(
        'time'      => ['1558432388750'],
        'action'    => 'lose',
        'target_id' => '76',
        'actor_id'  => ['87'],
        'type'      => 'a',
    ),
    array(
        'time'      => [0000000000000,'1558432437780','1558432449937'], // 連結した結果こうなる
        'action'    => 'get',
        'target_id' => '10',
        'actor_id'  => ['3','9','51'], // 連結した結果こうなる
        'type'      => 'a', // ここは a になる
    )    
);

該当の配列

こちらが素材となる配列です。

/*
$base_arr
元からある、0個以上の配列(今回は2つ)
*/
$base_arr = array(
    array(
        'time'      => ['1558432388750'],
        'action'    => 'lose',
        'target_id' => '76',
        'actor_id'  => ['87'],
        'type'      => 'a',
    ),
    array(
        'time'      => ['1558432437780','1558432449937'],
        'action'    => 'get',
        'target_id' => '10',
        'actor_id'  => ['9','51'],
        'type'      => 'b',
    )    
);

/*
$new_arr 
新しく連結される配列で、常に1つ
*/
$time_ux = ceil(microtime(true)*1000);
$new_arr = array(
    array(
        'time'      => [$time_ux],
        'action'    => 'get',
        'target_id' => '10',
        'actor_id'  => ['3'],
        'type'      => 'a',
    )
);


連結の条件としては、

➀ $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'の方にまで連結されてしまうのでしょうか。

試したこと

こちらが問題の発生するコードです。

// 素材となる配列
$base_arr = get_base_arr(); 
$new_arr = get_new_arr();

// $base_arr がない場合
if( empty($base_arr) || is_null($base_arr) ){
    $update_arr = $new_arr;
}

// すでに $base_arr がある場合
else{
    foreach ( $base_arr as $base_keys ){
        if( $base_keys['action'] == $new_arr[0]['action'] && $base_keys['target_id'] == $new_arr[0]['target_id'] ){
        for( $i = 0; $i < count($base_arr); $i++ ) {
            $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';
        }   
    }  
    $update_arr = $base_arr;
}

// 確認
var_export($update_arr);


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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

条件に一致した場合、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 21:20

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

    キャンセル

  • 2019/05/21 21:35

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

    キャンセル

  • 2019/05/21 21:56

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

    キャンセル

+1

こんな感じですか?

$base_arr = array(
    array(
        'time'      => ['1558432388750'],
        'action'    => 'lose',
        'target_id' => '76',
        'actor_id'  => ['87'],
        'type'      => 'a',
    ),
    array(
        'time'      => ['1558432437780','1558432449937'],
        'action'    => 'get',
        'target_id' => '10',
        'actor_id'  => ['9','51'],
        'type'      => 'b',
    )    
);
$time_ux = ceil(microtime(true)*1000);
$new_arr = array(
    array(
        'time'      => [$time_ux],
        'action'    => 'get',
        'target_id' => '10',
        'actor_id'  => ['3'],
        'type'      => 'a',
    )
);
$update_arr=array_map(function($x) use ($new_arr){
  if($x["target_id"]==$new_arr[0]["target_id"] and
     $x["action"]==$new_arr[0]["action"]){
    array_push($x["time"],$new_arr[0]["time"][0]);
    array_push($x["actor_id"],$new_arr[0]["actor_id"][0]);
    $x["type"]=$new_arr[0]["type"];
  }
  return $x;
},$base_arr);
print_r($update_arr);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/21 20:09

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

    キャンセル

  • 2019/05/21 20:19 編集

    ほぼイメージ通りです。useとかレベル高くてわからないですけどw、どうもありがとうございます。

    でも、new_arrのactor_idとtimeは先頭に連結したいというのがあります。
    ご回答のactor_idは「9-51-3」の順になっていますが、「3-9-51」を実現したいと考えていました。

    >target_idとactionがどれにも合致しなかったとき
    はい、そうです。合致しなければ新しい配列が増えます。

    キャンセル

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

  • ただいまの回答率 87.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る