【问题标题】:PHP: why do these output different results?PHP:为什么这些输出不同的结果?
【发布时间】:2018-01-14 04:48:16
【问题描述】:

我构建了两个版本的 PHP 7 函数,它接受一个数组,并返回一个数组列表,其中显示了原始数组成员的所有排列。例如,对于输入 [1,2,3],预期输出将是 1、2 和 3 的所有六个排列。

我希望该函数的两个版本都能提供相同的输出,但不知道为什么会这样。这是第一个(按预期工作):

function permutations(array $input): array {
  $func = function (array $selected, array $chooseFrom, array &$results) 
             use (&$func) {

    foreach ($chooseFrom as $k => $unchosen):
      $selectedCopy = $selected; // make a copy
      $chooseFromCopy = $chooseFrom; // make a copy

      $selectedCopy[] = $unchosen; // add the next unchosen item to selected list
      array_splice($chooseFromCopy, $k,1); // remove the item from chooseFrom list
      $func($selectedCopy, $chooseFromCopy, $results); // recursive call
    endforeach;

    // If we've used all items. Add selection to results
    if (empty($chooseFrom)) $results[] = $selected;
  };

  $results = [];
  $func([], $input, $results);
  return $results;
}

当我调用permutations([1,2]) 时,我得到了预期的结果:[[1,2],[2,1]]

这是该函数的非工作版本。唯一的区别在于foreach

function permutations2(array $input): array {

  $func = function (array $selected, array $chooseFrom, array &$results) 
             use (&$func) {

    foreach ($chooseFrom as $k => $unchosen):    
      $chooseFromCopy = $chooseFrom; // make a copy

      $selected[] = $unchosen; // add the next unchosen to the selected list
      array_splice($chooseFromCopy, $k, 1); // remove the item from chooseFrom list
      $func($selected, $chooseFromCopy, $results); // recursive call
    endforeach;

    // If we've used all items. Add selection to results
    if (empty($chooseFrom)) $results[] = $selected;
  };

  $results = [];
  $func([], $input, $results);
  return $results;
}

当我调用permutations2([1,2]) 时,我得到了一个不好的结果:[[1,2],[1,2,1]]

为什么有区别??

【问题讨论】:

  • 问题在于变量“$selected”保存了第一个for循环的第一次迭代的结果,在进入下一次循环迭代之前需要清除它。添加行“$selected = array();”在 endforeach 语句之前将使代码工作。

标签: php arrays pass-by-reference


【解决方案1】:

问题在于变量“$selected”保存了 for 循环的第一次迭代的结果,并且在进入循环的下一次迭代之前需要重新初始化它。在 for 循环之前将“$selected”存储在另一个变量(假设为 $tempselected)中,并在 endforeach 语句之前使用 $tempselected 重新初始化“$selected”变量将使代码正常工作。但是这种变化与函数的工作示例几乎相同:)

<?php

function permutations2(array $input): array {

  $func = function (array $selected, array $chooseFrom, array &$results) 
             use (&$func) {
    $selectedTemp = $selected;

    foreach ($chooseFrom as $k => $unchosen):    
      $chooseFromCopy = $chooseFrom; // make a copy

      $selected[] = $unchosen; // add the next unchosen to the selected list
      array_splice($chooseFromCopy, $k, 1); // remove the item from chooseFrom list
      $func($selected, $chooseFromCopy, $results); // recursive call
      $selected = $selectedTemp;
    endforeach;

    echo("<br>After For Loop <br>");
    // If we've used all items. Add selection to results
      if (empty($chooseFrom))  { $results[] = $selected;  }  
  };

  $results = [];
  $func([], $input, $results);
  return $results;
}
$res = permutations2(['a','b','c']);

【讨论】:

  • 刚刚测试了更多类型的输入值 - 如果输入数组大小大于 2,清除也无济于事。检查除了第一个版本之外是否有任何简单的方法来解决这个问题函数。
猜你喜欢
  • 1970-01-01
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
相关资源
最近更新 更多