Asked  7 Months ago    Answers:  5   Viewed   39 times

Supposing I have these 3 arrays

$array1 = array(1,2);
$array2 = array(4,5);
$array3 = array(7,8);

I need this output

1 4 7
1 4 8
1 5 7
1 5 8
2 4 7
2 4 8
2 5 7
2 5 8

One of my problems is that my array myght vary from 3 to 15 different arrays and each myght be empty (I might add a 0 just not to be empty) or have many values. If I have an empty array I also need to count that as a valid column. These values will be used to fill up a database in a specific order.

Is there any way I can do this?

 Answers

31

How many combinations are there?

So first the question how many combinations are there? And the answer is you have to multiply the amount of every array with each other.

So (c = amount1):

carray 1 * carray 2 * ... * carray n

And specific for your example:

carray 1 * carray 2 * carray 3 = 2 * 2 * 2 = 8

*1 And if you wonder why I chose c for amount, because of the function count() in php

Getting all combinations together

How do we get now all combinations with the amount of arrays, which we have?

We loop through all our combinations, which we already have(Starting off with one combination, an "empty combination" ($combinations = [[]];)), and for each combination we go through our next data array and combine each combination with each input data to a new combination.

Now we do this until we get the desired length for each combination.

So as an example:

Array with the elements (Empty array is '[]'):

[
    [1, 2],
    [3, 4]
]

                               //? new combinations for the next iteration
                               ?
array NAN*:

    Combinations:
                  - []         ?  -> []
                                  ?
array 1 [1,2]:      ???????????????
                    ?             ?
    Combinations:   v             v
                  - []    + 1  ?  -> [1]  
                  - []    + 2  ?  -> [2]   
                                  ?
array 2 [3,4]:      ???????????????
                    ?             ?
    Combinations:   v             v
                  - []    + 3  ?  -> [3]
                  - []    + 4  ?  -> [4]
                  - [1]   + 3  ?  -> [1,3]  //desired length 2 as we have 2 arrays 
                  - [1]   + 4  ?  -> [1,4]  //desired length 2 as we have 2 arrays 
                  - [2]   + 3  ?  -> [2,3]  //desired length 2 as we have 2 arrays 
                  - [2]   + 4  ?  -> [2,4]  //desired length 2 as we have 2 arrays    
                               //? All combinations here

* NAN: not a number

So as you can see in the above example we now have all combinations with the length of the amount of all arrays which we have.

But to get only the combinations with the desired length we are overwriting the result array each iteration, so that at the end only the combinations with the expected length are in the results array.

Code:

<?php

    $array1 = array(1,2);
    $array2 = array(4,5);
    $array3 = array(7,8);


    $combinations = [[]];
    $data = [
        $array1,
        $array2,
        $array3,
    ];
    $length = count($data);

    for ($count = 0; $count < $length; $count++) {
        $tmp = [];
        foreach ($combinations as $v1) {
            foreach ($data[$count] as $v2)
                $tmp[] = array_merge($v1, [$v2]);

        }
        $combinations = $tmp;
    }

    print_r($combinations);

?>

output:

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 4
            [2] => 7
        )
    //...
    [7] => Array
        (
            [0] => 2
            [1] => 5
            [2] => 8
        )

)

For associative arrays you only have to do a slight modification, which is:

  1. First assign the arrays keys to a variable with array_keys(), e.g.

    $keys = array_keys($data);
    
  2. Use the keys in the second foreach loop to access the data array, means from:

    foreach ($data[$count] as $v2)
    

    to:

    foreach ($data[$keys[$count]] as $v2)
Wednesday, March 31, 2021
 
Viralk
answered 7 Months ago
15

I've taken the cartesian function from this answer, and given the output you've wanted.

(Credit to sergiy for creating the function)

https://eval.in/199787

<?php

$array = Array
    (
    'colour' => Array
        (
        1130,
        1131,
        1132,
        1133
    ),
    'size' => Array
        (
        1069,
        1070
    )
);

echo "<pre>";
$arrFinalArray = cartesian($array);
foreach( $arrFinalArray as $arrIndie) {
    //We know each as 2 keys
    $arrKeys = array_keys($arrIndie);
    $arrValues = array_values($arrIndie);

    echo $arrKeys[0] ."  ". $arrValues[0] ." - ". $arrKeys[1] ." ". $arrValues[1] ."<br />";
}
echo "</pre>";


function cartesian($input) {
    // filter out empty values
    $input = array_filter($input);

    $result = array(array());

    foreach ($input as $key => $values) {
        $append = array();

        foreach($result as $product) {
            foreach($values as $item) {
                $product[$key] = $item;
                $append[] = $product;
            }
        }

        $result = $append;
    }

    return $result;
}
Wednesday, March 31, 2021
 
waylaidwanderer
answered 7 Months ago
39

When you set cell values individually, you have the option of setting the datatype explicitly, but when you use the fromArray() method, you don't have this option.

However, by default, PHP uses a default value binder to identify datatypes from the values passed, and set the cell datatype accordingly. This default behaviour is defined in a class /PHPExcel/Cell/DefaultValueBinder.php.

So you can create your own value binder, as described in the PHPExcel Documentation, that would set every value as a string datatype.

Something like:

class PHPExcel_Cell_MyColumnValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder
{
    protected $stringColumns = [];

    public function __construct(array $stringColumnList = []) {
        // Accept a list of columns that will always be set as strings
        $this->stringColumns = $stringColumnList;
    }

    public function bindValue(PHPExcel_Cell $cell, $value = null)
    {
        // If the cell is one of our columns to set as a string...
        if (in_array($cell->getColumn(), $this->stringColumns)) {
            // ... then we cast it to a string and explicitly set it as a string
            $cell->setValueExplicit((string) $value, PHPExcel_Cell_DataType::TYPE_STRING);
            return true;
        }
        // Otherwise, use the default behaviour
        return parent::bindValue($cell, $value);
    }
}

// Instantiate our custom binder, with a list of columns, and tell PHPExcel to use it
PHPExcel_Cell::setValueBinder(new PHPExcel_Cell_MyColumnValueBinder(['A', 'B', 'C', 'E', 'F']));

$objPHPExcel = new PHPExcel();
$objPHPExcel->getActiveSheet()->fromArray($dataArray,null,"A2");
Friday, May 28, 2021
 
Wilk
answered 5 Months ago
74
$arr_main_array = array('foo-test' => 123, 'other-test' => 456, 'foo-result' => 789);

foreach($arr_main_array as $key => $value){
    $exp_key = explode('-', $key);
    if($exp_key[0] == 'foo'){
         $arr_result[] = $value;
    }
}

if(isset($arr_result)){
    print_r($arr_result);
}
Wednesday, June 16, 2021
 
waylaidwanderer
answered 5 Months ago
69

This should work for you:

So what does this code do?

1. How many combinations are there?

So first the question how many combinations are there and the answer is you have to multiply the amount of every array with each other.

So (c = amount1):

carray 1 * carray 2 * ... * carray n

And specific for your example:

carray 1 * carray 2 = 3 * 3 = 9

*1 And if you wonder why I chose c for amount, because of the function count() in php

2. Getting all combinations

How do we get now all combinations with the length of the amount of all arrays?

Well pretty simple, we just loop through all combinations (at the start just an empty combination ([] == array())) which we already have with the next array until we get the desired length which we want, in this case the last iteration of the last array.

So as an example:

Array with the elements (Empty array is '[]'):

[
    [1, 2],
    [3, 4]
]

                               //new combinations for the next iteration
                               |
array NAN*:

    Combinations:
                  - []         |  -> []
                                  |
array 1 [1,2]:       -------------
                    |             |
    Combinations:   v             v
                  - []    + 1  |  -> [1]  
                  - []    + 2  |  -> [2]   
                                  |
array 2 [3,4]:       -------------
                    |             |
    Combinations:   v             v
                  - []    + 3  |  -> [3]
                  - []    + 4  |  -> [4]
                  - [1]   + 3  |  -> [1,3]
                  - [1]   + 4  |  -> [1,4]
                  - [2]   + 3  |  -> [2,3]
                  - [2]   + 4  |  -> [2,4]     
                               //^ All combinations here

* NAN: not a number

So as you can see in the above example we now have all combinations with the length of the amount of all arrays which we have.

But to get only the combinations with the desired length we are overwriting the result array each iteration, so that at the end only the combinations with the expected length are in the results array.

code:

<?php

    $data = [
            35 => ["green", "red", "brown"],
            36 => ["fox", "house", "dog"]
        ];

    $combinations = [[]];
    $comKeys = array_keys($data);


    for ($count = 0; $count < count($comKeys); $count++) {
        $tmp = [];
        foreach ($combinations as $v1) {
            foreach ($data[$comKeys[$count]] as $v2)
                $tmp[] = $v1 + [$comKeys[$count] => $v2];

        }
        $combinations = $tmp;
    }

    print_r($combinations);

?>

output:

Array
(
    [0] => Array
        (
            [35] => green
            [36] => fox
        )

    [1] => Array
        (
            [35] => green
            [36] => house
        )

    [2] => Array
        (
            [35] => green
            [36] => dog
        )

    [3] => Array
        (
            [35] => red
            [36] => fox
        )

    [4] => Array
        (
            [35] => red
            [36] => house
        )

    [5] => Array
        (
            [35] => red
            [36] => dog
        )

    [6] => Array
        (
            [35] => brown
            [36] => fox
        )

    [7] => Array
        (
            [35] => brown
            [36] => house
        )

    [8] => Array
        (
            [35] => brown
            [36] => dog
        )

)
Saturday, August 21, 2021
 
dimi
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :