如何组合PHP中具有相同关联键值的数组?

时间:2018-01-21 21:11:26

标签: php arrays wordpress associative-array

我正在尝试创建一个数组,从循环浏览wordpress中的帖子,构建一系列人物,他们玩过的游戏以及他们每场比赛发布的分数。

我目前的代码:

    $world_rank = [];
    while ( $the_query->have_posts() ) : $the_query->the_post();
          $category = get_the_category();
          $cat_name = $category[0]->cat_name;
          $score = get_field('score');
          $author = get_the_author();

          $array_size = sizeof($world_rank[$author]['games']);
          if( $array_size < 1 ){
            $world_rank[$author]['games'][] = ['name' =>  addslashes($cat_name), 'scores' => [$score] ];
          }else{
            // loop through the array and see if they have been similar game names if so, add them to push array
            $i = 0;
            foreach($world_rank[$author]['games'] as $game){
              if($game['name'] == $cat_name){
                echo 'Same name ' .$game['scores']. ' score is '.$score.'</br>';
                array_push($game['scores'], $score);
// this doesn't seem to work
                // break;
              }
              else if($game['name'] !== $cat_name && $i == $array_size - 1 ){ //
                // if the names are not the same create a new array for the other game
                $world_rank[$author]['games'][] = ['name' =>  addslashes($cat_name), 'scores' => [$score] ];
              }
              $i++;
            }
          }
        endwhile;

上面的输出给出了这个:

$world_rank = array (
      'frantheman' => 
      array (
        'games' => 
        array (
          0 => 
          array (
            'name' => 'Candy',
            'scores' => 
            array (
              0 => '23',
            ),
          ),
          1 => 
          array (
            'name' => 'PopCorn',
            'scores' => 
            array (
              0 => '25',
            ),
          ),
          2 => 
          array (
            'name' => 'Chocolate',
            'scores' => 
            array (
              0 => '5',
            ),
          ),
          3 => 
          array (
            'name' => 'Candy',
            'scores' => 
            array (
              0 => '25',
            ),
          ),
        )
      );

我怎样才能让world_rank数组拥有&#39; Candy&#39;由于&#39; Candy&#39;值在数组中出现两次,并结合“糖果”的分数。键。所以现在看起来像:

$world_rank = array (
  'frantheman' => 
  array (
    'games' => 
    array (
      0 => 
      array (
        'name' => 'Candy',
        'scores' => 
        array (
          0 => '23',
          1 => '25' 
        ),
      ),
      1 => 
      array (
        'name' => 'PopCorn',
        'scores' => 
        array (
          0 => '25',
        ),
      ),
      2 => 
      array (
        'name' => 'Chocolate',
        'scores' => 
        array (
          0 => '5',
        ),
      )
  );

正如您所看到的,在新阵列中,“糖果”#39;有2个阵列的分数。任何有关这方面的帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:2)

您的代码中存在一个小错误。如果你想在foreach中修改$ game,你需要通过引用来遍历它。只是做你的foreach:

foreach($world_rank[$author]['games'] as &$game){

然后,您实际修改了实际得分数组,并且不创建本地副本。 (如果您想了解更多相关内容,请撰写Google PHP副本。)

您还需要break语句,否则您将在循环结束条件中创建另一个元素。但是你已经把它放在了正确的地方;不予评论。

<强>替代

我在下面添加的内容是错误的!已删除。

答案 1 :(得分:1)

编辑经过OP的多次反复,我已经重写了我的答案和OP的原始剧本。

这是可测试的脚本:(Demo

$raw_input=[
    ['frantheman','Candy Crush','11'],
    ['frantheman','Candy Crush','5'],
    ['frantheman','Candy Crush','4'],
    ['frantheman','Candy Crush','23'],
    ['frantheman','Candy Crush','25'],
    ['frantheman','Candy Crush',NULL],
    ['frantheman','Blackjack','68'],
    ['frantheman','Blackjack',NULL],
    ['frantheman','Blackjack','90'],
    ['frantheman','Killer Instinct','25'],
    ['frantheman','Grand Theft Auto V','5'],
    ['frantheman','Counter-Strike: Global Offensive','67'],
    ['frantheman','Lawbreakers','456'],
    ['Braconda','Overwatch','24459'],
    ['Braconda','Overwatch','70'],
    ['ScotGamer1','Overwatch','24359'],
    ['ScotGamer1','Blackjack','21'],
    ['ScotGamer1','Grand Theft Auto V','23386'],
    ['ScotGamer1','Dota 2','2560'],
    ['John','Counter-Strike: Global Offensive','75656'],
    ['John','Counter-Strike: Global Offensive','19000'],
    ['John','Team Fortress 2','8686'],
    ['John','Team Fortress 2','7755'],
    ['John','Dota 2','86766'],
    ['John','Dota 2','12345'],
    ['John','Candy Crush','9999999999999999'],
    ['John','Candy Crush','66'],
    ['John','PLAYERUNKNOWN’S BATTLEGROUNDS','42'],
    ['John','Lawbreakers','5345345'],
    ['John','Lawbreakers','54321']
];

$user_game_stats=[];  // this will be the final output array containing all statistics
foreach($raw_input as $a){
    $game = addslashes($a[1]);
    $user = $a[0];
    $score=intval($a[2]);

    $user_game_stats[$user][$game]['scores'][]=$score;
    if(!isset($user_game_stats[$user][$game]['high_score']) || $score>$user_game_stats[$user][$game]['high_score']){
        $user_game_stats[$user][$game]['high_score']=$score;
        $user_high_scores_by_game[$game][$user]=$score;  // this is a temporary array for calculating rank
    }
}

// a second loop is essential because the rank calculations involve the users' high scores and player count per game
foreach($user_high_scores_by_game as $game=>$user_scores){
    $total_game_users=count($user_scores);
    arsort($user_scores);  // sort the users by their high score in DESC order and preserve the keys (usernames)
    $ordered_users=array_keys($user_scores);  // high scores are no longer required, we just want to determine rank
    foreach($ordered_users as $number=>$user){
        $user_game_stats[$user][$game]['rank']=++$number;  // starts from zero so $number is modified/increased by one for human-friendly rank
        $user_game_stats[$user][$game]['efficiency']=$number / ($total_game_users * .1); // I don't like "efficiency" but can't offer a better term
        // you may want to introduce rounding on the efficiency calculation
    }
}
var_export($user_game_stats);

输出:

array (
  'frantheman' => 
  array (
    'Candy Crush' => 
    array (
      'scores' => 
      array (
        0 => 11,
        1 => 5,
        2 => 4,
        3 => 23,
        4 => 25,
        5 => 0,
      ),
      'high_score' => 25,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
    'Blackjack' => 
    array (
      'scores' => 
      array (
        0 => 68,
        1 => 0,
        2 => 90,
      ),
      'high_score' => 90,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
    'Killer Instinct' => 
    array (
      'scores' => 
      array (
        0 => 25,
      ),
      'high_score' => 25,
      'rank' => 1,
      'efficiency' => 10.0,
    ),
    'Grand Theft Auto V' => 
    array (
      'scores' => 
      array (
        0 => 5,
      ),
      'high_score' => 5,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
    'Counter-Strike: Global Offensive' => 
    array (
      'scores' => 
      array (
        0 => 67,
      ),
      'high_score' => 67,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
    'Lawbreakers' => 
    array (
      'scores' => 
      array (
        0 => 456,
      ),
      'high_score' => 456,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
  ),
  'Braconda' => 
  array (
    'Overwatch' => 
    array (
      'scores' => 
      array (
        0 => 24459,
        1 => 70,
      ),
      'high_score' => 24459,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
  ),
  'ScotGamer1' => 
  array (
    'Overwatch' => 
    array (
      'scores' => 
      array (
        0 => 24359,
      ),
      'high_score' => 24359,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
    'Blackjack' => 
    array (
      'scores' => 
      array (
        0 => 21,
      ),
      'high_score' => 21,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
    'Grand Theft Auto V' => 
    array (
      'scores' => 
      array (
        0 => 23386,
      ),
      'high_score' => 23386,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
    'Dota 2' => 
    array (
      'scores' => 
      array (
        0 => 2560,
      ),
      'high_score' => 2560,
      'rank' => 2,
      'efficiency' => 10.0,
    ),
  ),
  'John' => 
  array (
    'Counter-Strike: Global Offensive' => 
    array (
      'scores' => 
      array (
        0 => 75656,
        1 => 19000,
      ),
      'high_score' => 75656,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
    'Team Fortress 2' => 
    array (
      'scores' => 
      array (
        0 => 8686,
        1 => 7755,
      ),
      'high_score' => 8686,
      'rank' => 1,
      'efficiency' => 10.0,
    ),
    'Dota 2' => 
    array (
      'scores' => 
      array (
        0 => 86766,
        1 => 12345,
      ),
      'high_score' => 86766,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
    'Candy Crush' => 
    array (
      'scores' => 
      array (
        0 => 9999999999999999,
        1 => 66,
      ),
      'high_score' => 9999999999999999,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
    'PLAYERUNKNOWN’S BATTLEGROUNDS' => 
    array (
      'scores' => 
      array (
        0 => 42,
      ),
      'high_score' => 42,
      'rank' => 1,
      'efficiency' => 10.0,
    ),
    'Lawbreakers' => 
    array (
      'scores' => 
      array (
        0 => 5345345,
        1 => 54321,
      ),
      'high_score' => 5345345,
      'rank' => 1,
      'efficiency' => 5.0,
    ),
  ),
)

这是我的代码段的WP实现:

$user_game_stats=[];  // this will be the final output array containing all statistics
while($the_query->have_posts()){
    $the_query->the_post();
    $game = addslashes(get_the_category()[0]->cat_name);
    $user = get_the_author();
    $score=intval(get_field('score'));

    $user_game_stats[$user][$game]['scores'][]=$score;
    if(!isset($user_game_stats[$user][$game]['high_score']) || $score>$user_game_stats[$user][$game]['high_score']){
        $user_game_stats[$user][$game]['high_score']=$score;
        $user_high_scores_by_game[$game][$user]=$score;  // this is a temporary array for calculating rank
    }
}

// a second loop is essential because the rank calculations involve the users' high scores and player count per game
foreach($user_high_scores_by_game as $game=>$user_scores){
    $total_game_users=count($user_scores);
    arsort($user_scores);  // sort the users by their high score in DESC order and preserve the keys (usernames)
    $ordered_users=array_keys($user_scores);  // high scores are no longer required, we just want to determine rank
    foreach($ordered_users as $number=>$user){
        $user_game_stats[$user][$game]['rank']=++$number;  // starts from zero so $number is modified/increased by one for human-friendly rank
        $user_game_stats[$user][$game]['efficiency']=$number / ($total_game_users * .1); // I don't like "efficiency" but can't offer a better term
        // you may want to introduce rounding on the efficiency calculation
    }
}
var_export($user_game_stats);