【问题标题】:How to combine an array that has the same associative key values in PHP?如何在 PHP 中组合具有相同关联键值的数组?
【发布时间】:2018-06-30 12:06:14
【问题描述】:

我正在尝试通过循环访问 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 数组具有 'Candy' 值作为 1 数组,因为 'Candy' 值在数组中出现两次,并结合 'Candy' 键的分数。所以让它现在看起来像:

$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',
        ),
      )
  );

如您所见,在新数组中,'Candy' 有 2 个用于分数的数组。对此的任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 请提供您如何创建第一个数组的代码
  • @Tarasovych 已更新。感谢您的评论让我把它放进去,而不是像其他人那样投反对票。
  • 你必须使用array_push()将所有游戏的分数放入存在数组中,使用foreach()
  • 谢谢,但我就是这么做的。就在这里:f($game['name'] == $cat_name){ echo 'Same name ' .$game['scores']. ' 分数是 '.$score.''; array_push($game['scores'], $score); // 这似乎不起作用 // break; }
  • 如果我在该条件下进行回显,我会看到它在“Candy”名称键处添加到数组中。但是,当我打印数组的最终结果时,我得到了我在问题中显示的第一个输出。

标签: php arrays wordpress associative-array


【解决方案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,
    ),
  ),
)

这是我的 sn-p 的 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);

【讨论】:

    【解决方案2】:

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

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

    然后您实际上修改了实际的分数数组,而不是创建本地副本。 (如果您想了解更多信息,请在写入时使用 Google PHP 副本)。

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

    替代方案

    我在下面添加的选项有误!已删除。

    【讨论】:

      猜你喜欢
      • 2015-01-04
      • 2017-07-07
      • 1970-01-01
      • 2014-03-12
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 2014-09-17
      • 1970-01-01
      相关资源
      最近更新 更多