从PHP 2D数组的每一行中查找包含一个值的元素的每种组合

时间:2019-01-27 07:08:59

标签: php recursion multidimensional-array

我在项目中使用了更大的数组,但为了简化起见,假设我们有一个3x3数组:

if(getIntent() != null){
  String path = getIntent().getStringExtra("image");
  Glide.with(this)
    .load(path)
    .into(imageView);
}

我想找到每行包括一个值的总和的每种组合,即1 + 4 + 7、1 + 4 + 8、1 + 4 + 9、1 + 5 + 7、1 + 5 + 8 ,1 + 5 + 9,1 + 6 + 7,1 + 6 + 8,1 + 6 + 9,2 + 4 + 7,2 + 4 + 8,2 + 4 + 9,2 + 5 + 7,。 ..

希望这种模式很明显。我先尝试了一个嵌套循环(列,然后是行),但是并没有提供所有组合。经过大量搜索之后,我对解决方案需要递归感到很有信心,但是每次尝试为此编写递归函数时,我都会感到困惑。

虽然非常感谢工作代码,但对我来说更重要的是了解问题和解决方案。

3 个答案:

答案 0 :(得分:2)

给出数组中未知数量的行和列,获得所需结果的最佳方法是使用递归(否则,您将必须编写任意数量的嵌套循环)。此函数在数组的每一行上递归,并返回两个结果之一:

  1. 如果我们在数组的最后一行,则返回该行;
  2. 否则,返回当前行与数组平衡结果之间的叉积(使用两个嵌套的foreach循环)。我们使用array_shift来获取当前行,并将其从数组中删除。

代码如下:

function find_paths($array) {
    if (count($array) == 1) return $array[0];
    $output = array();
    foreach (array_shift($array) as $v1) {
        foreach (find_paths($array) as $v2) {
            $output[] = array_merge(array($v1), is_array($v2) ? $v2 : array($v2));
        }
    }
    return $output;
}

使用示例数据:

$a = Array( Array(1,2,3),
            Array(4,5,6),
            Array(7,8,9) );
$combinations = find_paths($a);

该函数执行以下一系列操作:

  1. 将第1行(1, 2, 3)的叉积与函数输出的结果相乘,得到数组((4, 5, 6), (7, 8, 9))的余额;
  2. 第一次递归:将第2行(4, 5, 6)的叉积与函数输出((7, 8, 9))的叉积相乘;
  3. 第二个递归:至此,数组(7, 8, 9)中仅剩一行,因此我们将其返回;
  4. 第一次递归:计算(4, 5, 6)(7, 8, 9) = ((4, 7), (4, 8), (4, 9), (5, 7), (5, 8), (5, 9), (6, 7), (6, 8), (6, 9))的叉积并返回;
  5. (1, 2, 3)((4, 7), (4, 8), (4, 9), (5, 7), (5, 8), (5, 9), (6, 7), (6, 8), (6, 9))的叉积,并将其返回。

提供以下输出:

Array (
    [0] => Array ( [0] => 1 [1] => 4 [2] => 7 )
    [1] => Array ( [0] => 1 [1] => 4 [2] => 8 )
    [2] => Array ( [0] => 1 [1] => 4 [2] => 9 )
    [3] => Array ( [0] => 1 [1] => 5 [2] => 7 )
    [4] => Array ( [0] => 1 [1] => 5 [2] => 8 )
    [5] => Array ( [0] => 1 [1] => 5 [2] => 9 )
    [6] => Array ( [0] => 1 [1] => 6 [2] => 7 )
    [7] => Array ( [0] => 1 [1] => 6 [2] => 8 )
    [8] => Array ( [0] => 1 [1] => 6 [2] => 9 )
    [9] => Array ( [0] => 2 [1] => 4 [2] => 7 )
   [10] => Array ( [0] => 2 [1] => 4 [2] => 8 )
   [11] => Array ( [0] => 2 [1] => 4 [2] => 9 )
   [12] => Array ( [0] => 2 [1] => 5 [2] => 7 )
   [13] => Array ( [0] => 2 [1] => 5 [2] => 8 )
   [14] => Array ( [0] => 2 [1] => 5 [2] => 9 )
   [15] => Array ( [0] => 2 [1] => 6 [2] => 7 )
   [16] => Array ( [0] => 2 [1] => 6 [2] => 8 )
   [17] => Array ( [0] => 2 [1] => 6 [2] => 9 )
   [18] => Array ( [0] => 3 [1] => 4 [2] => 7 )
   [19] => Array ( [0] => 3 [1] => 4 [2] => 8 )
   [20] => Array ( [0] => 3 [1] => 4 [2] => 9 )
   [21] => Array ( [0] => 3 [1] => 5 [2] => 7 )
   [22] => Array ( [0] => 3 [1] => 5 [2] => 8 )
   [23] => Array ( [0] => 3 [1] => 5 [2] => 9 )
   [24] => Array ( [0] => 3 [1] => 6 [2] => 7 )
   [25] => Array ( [0] => 3 [1] => 6 [2] => 8 )
   [26] => Array ( [0] => 3 [1] => 6 [2] => 9 )
)

如果您随后想要获取总和,则可以简单地在数组上使用array_map,调用array_sum以获取每个元素的总和:

$sums = array_map(function ($v) { return array_sum($v);}, $combinations);

输出:

Array (
    [0] => 12
    [1] => 13
    [2] => 14
    [3] => 13
    [4] => 14
    [5] => 15
    [6] => 14
    [7] => 15
    [8] => 16
    [9] => 13
   [10] => 14
   [11] => 15
   [12] => 14
   [13] => 15
   [14] => 16
   [15] => 15
   [16] => 16
   [17] => 17
   [18] => 14
   [19] => 15
   [20] => 16
   [21] => 15
   [22] => 16
   [23] => 17
   [24] => 16
   [25] => 17
   [26] => 18 
)

Demo on 3v4l.org

答案 1 :(得分:1)

修改了一段时间后,我发现了另一个解决方案,该解决方案比尼克的解决方案或我的原始答案都快得多,并且占用的内存更少。当使用更大和更多的阵列时,这一点很重要。例如,尝试使用9 x 9(1.34亿个组合)代替3 x 3(27个组合)。

尼克提供的代码不仅可以按要求工作,而且可以得到很好的解释,仍然值得接受。另外,此代码借鉴了Nick的一些逻辑。

性能窍门是,我们只求和而不是找到所有组合然后求和。这样,我们就不会创建潜在的大型阵列,而只是创建一个潜在的大型阵列。

编辑:通过引用传递$sums而不是使用array_merge可以节省更多的时间和内存。代码已更新。

function combo_sums($arrays, $sum = 0, &$sums = []) {
    $array = array_shift($arrays);
    if (count($arrays) > 0)
        foreach ($array as $value)
            combo_sums($arrays, $sum + $value, $sums);
    else
        foreach ($array as $value)
            $sums[] = $sum + $value; # These are the final sums.
    return $sums;
}

答案 2 :(得分:0)

更多搜索后,我在这里找到了解决方案:https://gist.github.com/cecilemuller/4688876

我使用上面的示例数据对其进行了测试,它提供了所需的确切组合。如预期的那样,使用array_map按照尼克的答案查找总和。

令我惊讶的是,它不依赖于递归,而是三个嵌套循环。希望我能全神贯注于它的工作原理。