当前位置: 首页 > 面试题库 >

使用PHP关联数组查找笛卡尔积

易和怡
2023-03-14
问题内容

假设我有一个如下数组:

Array
(
    [arm] => Array
        (
            [0] => A
            [1] => B
            [2] => C
        )
    [gender] => Array
        (
            [0] => Female
            [1] => Male
        )
    [location] => Array
        (
            [0] => Vancouver
            [1] => Calgary
        )
)

如何在保留外部关联数组的键并将其用于内部键的同时找到笛卡尔乘积?该算法的结果应为:

Array
(
    [0] => Array
        (
            [arm] => A
            [gender] => Female
            [location] => Vancouver
        )

    [1] => Array
        (
            [arm] => A
            [gender] => Female
            [location] => Calgary
        )

    [2] => Array
        (
            [arm] => A
            [gender] => Male
            [location] => Vancouver
        )

...etc.

我查找了许多笛卡尔乘积算法,但是我对如何保留关联键的细节感到困惑。我正在使用的当前算法仅给出数字索引:

    $result = array();
    foreach ($map as $a) {
        if (empty($result)) {
            $result = $a;
            continue;
        }
        $res = array();
        foreach ($result as $r) {
            foreach ($a as $v) {
                $res[] = array_merge((array)$r, (array)$v);
            }
        }
        $result = $res;
    }

    print_r($result);

任何帮助,将不胜感激。


问题答案:

这是我不会感到羞耻的解决方案。

基本原理

像您的示例一样,假设我们有一个$input带有N子数组的输入数组。每个子数组都有Cn项目,其中nindex在里面$input,键为Kn。我将把th子数组的ith项n称为Vn,i

可以通过归纳证明以下算法有效(排除错误):

1)对于N = 1,笛卡尔乘积仅是array(0 => array(K1 => V1,1), 1 => array(K1 => V1,2), ... )-总共C1个项。这可以用一个简单的方法完成foreach

2)假设$result已经保存了前N-1个子数组的笛卡尔积。$result和第N个子数组的笛卡尔积可以通过以下方式产生:

3)在里面的每个项目(数组)中$product,添加值KN => VN,1。记住结果项(具有附加值);我将其称为$item

4a)对于内部的每个数组$product

4b)对于集合中的每个值VN,2 ... VN,CN,将其添加到$product的副本中$item,但使用键将值更改KNVN,m(对于所有2 <= m <= CN)。

两次迭代4a(在上$product)和4b(在第N个输入子数组上)最终都$result具有CN迭代之前每个项目的项目,因此最后$result确实包含前N个子数组的笛卡尔积。

因此,该算法将适用于任何N。

这比原本应该的难写。 我的正式证明肯定变得生锈了。

function cartesian($input) {
    $result = array();

    while (list($key, $values) = each($input)) {
        // If a sub-array is empty, it doesn't affect the cartesian product
        if (empty($values)) {
            continue;
        }

        // Seeding the product array with the values from the first sub-array
        if (empty($result)) {
            foreach($values as $value) {
                $result[] = array($key => $value);
            }
        }
        else {
            // Second and subsequent input sub-arrays work like this:
            //   1. In each existing array inside $product, add an item with
            //      key == $key and value == first item in input sub-array
            //   2. Then, for each remaining item in current input sub-array,
            //      add a copy of each existing array inside $product with
            //      key == $key and value == first item of input sub-array

            // Store all items to be added to $product here; adding them
            // inside the foreach will result in an infinite loop
            $append = array();

            foreach($result as &$product) {
                // Do step 1 above. array_shift is not the most efficient, but
                // it allows us to iterate over the rest of the items with a
                // simple foreach, making the code short and easy to read.
                $product[$key] = array_shift($values);

                // $product is by reference (that's why the key we added above
                // will appear in the end result), so make a copy of it here
                $copy = $product;

                // Do step 2 above.
                foreach($values as $item) {
                    $copy[$key] = $item;
                    $append[] = $copy;
                }

                // Undo the side effecst of array_shift
                array_unshift($values, $product[$key]);
            }

            // Out of the foreach, we can add to $results now
            $result = array_merge($result, $append);
        }
    }

    return $result;
}

用法

$input = array(
    'arm' => array('A', 'B', 'C'),
    'gender' => array('Female', 'Male'),
    'location' => array('Vancouver', 'Calgary'),
);

print_r(cartesian($input));


 类似资料:
  • 问题内容: 我想找到元素集的笛卡尔积。这是一个例子 笛卡尔积是, abc aba acc aca bbc bba bcc bca 笛卡尔积是, zbc ybc xbc 因此,我正在考虑一种在Java中执行的算法,该算法可以在一开始就找到在编译时定义的特定数量组的笛卡尔积。 问题答案: 您可以使用该方法从谷歌的番石榴库生成笛卡尔产品: 如果一切都那么简单!

  • 问题内容: 您将如何在JavaScript中实现多个数组的笛卡尔积? 举个例子, 应该回来 问题答案: 这是使用和提供的解决问题的功能解决方案(没有任何 可变变量 !),该提供者为:

  • 的结果将是二维数组: 我试图做的是使用流在Java中编写这个笛卡尔乘积函数。 到目前为止,我有以下Java版本: 我对问题的猜测是: 我需要在某个地方使用收集器(可能在之后) 标识的数据类型错误

  • 本文向大家介绍PHP笛卡尔积实现算法示例,包括了PHP笛卡尔积实现算法示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP笛卡尔积实现算法。分享给大家供大家参考,具体如下: 最终输出格式 Array (     [0] => 1,3,76     [1] => 1,3,6     [2] => 1,3,1     [3] => 1,3,0     [4] => 1,5,76    

  • 主要内容:Oracle CROSS JOIN子句简介,Oracle Cross Join示例在本教程中,您将学习如何使用Oracle 创建连接表的笛卡尔积。 Oracle CROSS JOIN子句简介 在数学中,给定两个集合和,的笛卡尔乘积是所有有序对(,)的集合,属于,属于。 要在Oracle中创建表的笛卡尔乘积,可以使用子句。 以下说明了子句的语法: 与其他连接(如或)不同,没有连接谓词的子句。 当执行两个没有关系的表的交叉连接时,将得到两个表的行和列的笛卡尔乘积。 当您想要生成大量

  • 问题内容: 我有两个pandas数据框: 获得其笛卡尔积的最佳实践是什么(当然不用像我这样明确地编写它)? 问题答案: 如果每行都有一个重复的键,则可以使用merge生成笛卡尔乘积(就像在SQL中一样)。 输出: