小范围/巨大的挫败感之谜:php中的错误数组行为


Small scope/huge frustration mystery: buggy array behavior in php

太疯狂了!我有一个100%可复制的错误,它只发生在几行代码中,但我一生都无法确定问题是什么。

我的项目是一个健身器,神秘之处包括两个功能:

  • get_pairings:它制作了一组$togeter_pairs(简单)和$mixed_pairs(烦人),并将它们组合成$all_pairs,用于进行锻炼
  • make_mixed_paries:这有不同的逻辑,取决于它是伴侣还是单独锻炼。这两种情况都返回一组$mixed_pairs(格式完全相同),由上面的函数调用

症状/线索:

  1. 如果是单独训练,$all_pairs将只包含$mixed_pairs(因为根据定义,$togeter_pairs仅用于合作训练)

  2. 在合作伙伴训练的情况下,当我在get_pairings()中组合两组时,$all_pairs只成功地获得了我给出的第一组!(如果我在步骤2中交换这些行,并首先添加$together_pairs,则$all_pairs只包含这些行。如果我首先添加$mixed_pairs,则$all_pairs仅包含这些行)。

  3. 然后,如果我取消对make_mixed_pairs()中倒数第二行的注释,只是为了进行故障排除,看看会发生什么,那么$all_pairs确实成功地包含了这两组的练习!

这表明问题是我在make_mixed_pairs()中制作数组时出错了,但我确认在这两种情况下生成的格式是相同的。

有人看到我还缺了什么吗?到目前为止,我已经缩小这个bug 4个小时了——我无法缩小它,也看不出有什么问题:(

更新:我更新了make_mixed_pairs()中的for循环,使其停止在$mixed_pair_count-1(而不仅仅是$mixed_pair_count),现在我有时会在$all_pairs结果中混合一个"togeter_pair";奇怪的是,每次都是同一个该死的。虽然它不是"固定的",因为当我再次改变在get_pairings中添加两个集合的顺序时,当我首先添加$togeter_pairs时,那么$all_pairs就是完整的——这太奇怪了。。。

以下是函数:first get_pairings(相关部分正好在步骤2之前和之后):

/**
* Used in make_workout.php: take the user's available resources, and return valid exercises
*/
function get_pairings($exercises, $count, $outdoor_partner_workout)      
{
// 1. Prep our variables, and put exercises into the appropriate buckets
    $mixed_exercises = array();
    $together_pairs = array();
    $mixed_pairs = array();
    $all_pairs = array();
    $selected_pairs = array();
    // Sort the valid exercises: self_pairing exercises go as they are, with extra
    // array for consistent formatting. Mixed ones go into $mixed_exercises array 
    // for more specialized pairing in make_mixed_pairs
    foreach($exercises as $exercise)
    {
        if ($exercise['self_pairing'])
        {
            $pair = array($exercise);
            array_push($together_pairs, [$pair]); 
        }
        else 
            {
                $this_exercise = array($exercise);
                array_push($mixed_exercises, $this_exercise); 
            }
    }
    // Now get the mixed_pairs 
    $mixed_pairs = make_mixed_pairs($mixed_exercises, $outdoor_partner_workout);  
// 2. combine together into one set, and select random pairs for the workout
    // Add both sets to the array of all pairs (to pick from afterward)
    $all_pairs += $mixed_pairs;
    $all_pairs += $together_pairs;
    // Now let's choose at random our desired # of pairs, and save them in $selected_pairs
    $pairing_keys = array_rand($all_pairs, $count);
    foreach($pairing_keys as $key)
    {
        array_push($selected_pairs, $all_pairs[$key]);
    }    
    // Finally, shuffle it so we don't always see the self-pairs first
    shuffle($selected_pairs);    
    return $selected_pairs;
}

另一种情况是make_mixed_pars:有两种情况,第一种情况很复杂(显示错误),第二种情况很简单(有效):

/**
* Used by get_pairings: in case of a partner workout that has open space (where 
* one person can travel to a point while the other does an exercise til they return)
* we'll pair exercises in a special way.  (If not, fine to grab random pairs)
*/    
function make_mixed_pairs($mixed_exercises, $outdoor_partner_workout)      
{
    $mixed_pairs = array();
    // When it's an outdoor partner workout, we want to pair travelling with stationary
    // put them into arrays and then we'll make pairs using one from each
    if ($outdoor_partner_workout)
    {
        $mixed_travelling = array();
        $mixed_stationary = array();        
        foreach($mixed_exercises as $exercise)
        {
            if ($exercise[0]['travelling'])
            {
                array_push($mixed_travelling, $exercise);
            }
            else
            {
                array_push($mixed_stationary, $exercise);
            }
        }
        shuffle($mixed_travelling);
        shuffle($mixed_stationary);
        // determine the smaller set, and pair exercises that many times
        $mixed_pair_count = min(count($mixed_travelling), count($mixed_stationary));
        for ($i=0; $i < $mixed_pair_count; $i++)
        {
            $this_pair = array($mixed_travelling[$i], $mixed_stationary[$i]);
            array_push($mixed_pairs, $this_pair);  // problem is adding them here- we get only self_pairs
        }
    }    
    // Otherwise we can just grab pairs from mixed_exercises
    else 
        {
            // shuffle the array so it's in random order, then chunk it into pairs
            shuffle($mixed_exercises);
            $mixed_pairs = array_chunk($mixed_exercises, 2);
        }
    // $mixed_pairs = array_chunk($mixed_exercises, 2);  // when I replace it with this, it works
    return $mixed_pairs;
}  

看在Pete的份上:我向一位朋友提到了这一点,他告诉我联合在php中是偶然的,我应该使用array_merge。

我更换了这些线路:

$all_pairs += $together_pairs;
$all_pairs += $mixed_pairs;

这个:

$all_pairs = array_merge($together_pairs, $mixed_pairs);

现在一切都正常了