fcastillo
fcastillo

Reputation: 948

Combinations array into array in PHP

I will try to explain everything :)

I have 2 arrays:

$packs = array(
  array(
    'name' => 'Pack 1',
    'zones' => array(
      array('zone' => 2),
      array('zone' => 2),
    )
  ),
  array(
    'name' => 'Pack 2',
    'zones' => array(
      array('zone' => 2),
      array('zone' => 2),
      array('zone' => 2),
    )
  ),
  array(
    'name' => 'Pack 3',
    'zones' => array(
      array('zone' => 2),
      array('zone' => 3),
    )
  ),
  array(
    'name' => 'Pack 4',
    'zones' => array(
      array('zone' => 3),
      array('zone' => 3),
    )
  )
);And products:

$products = array(
    array(
        'id' => '1',
        'zone' => '2'
    ),
    array(
        'id' => '8',
        'zone' => '2'
    ),
    array(
        'id' => '13',
        'zone' => '3'
    ),
    array(
        'id' => '11',
        'zone' => '2'
    ),
    array(
        'id' => '10',
        'zone' => '2'
    ),
    array(
        'id' => '12',
        'zone' => '3'
    )
);

Then I would like to have all $packs zones combination with those products zones. For example, products_zones are 2, 2, 3, 2, 2, 3 then I would like something like this:

Packs:

I'm trying to do that with recursive function but doesn't work. I leave here a link with code:

function search_recursive( $packs = array(), $products = array(), $packs_in = array(), $pass = null ) {
    foreach ($packs as $index => $pack) {
        // Get zones to compare
        $arr_zones = array_column($pack['zonas'], 'zona');

        $products_zones = array_column($products, 'zone');

        // Check if pack zones are in product zones
        $cheak_arr = [];
        $arr_zones_temp = $arr_zones;
        foreach ($products_zones as $index2 => $temp_zone) {
            if ( in_array($temp_zone, $arr_zones_temp) ) {
                $cheak_arr[] = $temp_zone;

                foreach ($arr_zones_temp as $key => $value) {
                    if ( $value == $temp_zone ) {
                        unset($arr_zones_temp[$key]);
                        break;
                    }
                }
            }

        }

        if ( count($arr_zones) == count($cheak_arr) ) {
            // I create a index for first time
            $custom_index = ($pass == null) ? $index : $pass;

            // Add pack to array if pack zones are in product zones
            if ( !isset($packs_in[$custom_index]) ) {
                $packs_in[$custom_index] = [
                    'packs' => array($pack)
                ];
            }
            else {
                $packs_in[$custom_index]['packs'][] = $pack;
            }

            // Remove products that have zones same in pack
            $temp_prod = $products;
            foreach ($arr_zones as $zone) {
                foreach ($temp_prod as $key => $value) {
                    if ( $value['zone'] == $zone ) {
                        unset($temp_prod[$key]);
                        break;
                    }
                }
            }

            if ( $pass != null ) {
                $products = $temp_prod;
            }

            if ( !empty($temp_prod) ) {
                // Call myself with less products and index defined
                $packs_in = search_recursive( $packs, $temp_prod, $packs_in, $custom_index );
            }
            else if ( $pass != null ) {
                break;
            }
        }
    }

    return $packs_in;
}

Upvotes: 0

Views: 41

Answers (1)

Felippe Duarte
Felippe Duarte

Reputation: 15131

I think I got what you need, but I'm still a bit confused. Anyway, I suggest you to simplify you "packs" array like my code below:

<?php

$packs = array(
  array(
    'name' => 'Pack 1',
    'zones' => array(2,2),
  ),
  array(
    'name' => 'Pack 2',
    'zones' => array(2,2,2),
  ),
  array(
    'name' => 'Pack 3',
    'zones' => array(2,3),
  ),
  array(
    'name' => 'Pack 4',
    'zones' => array(3,3),
  )
);

$products = array(
    array(
        'id' => '8',
        'zone' => '2'
    ),
    array(
        'id' => '13',
        'zone' => '3'
    ),
    array(
        'id' => '11',
        'zone' => '2'
    ),
    array(
        'id' => '10',
        'zone' => '2'
    ),
    array(
        'id' => '12',
        'zone' => '3'
    )
);

$product_zones = array_column($products, 'zone');
//let's order an change to a sequence of numbers like 22233
sort($product_zones);
$product_zones = join('', $product_zones);

$combinations = [];

//here we iterate through all packs 1->2,3,4; 2->3,4 3->4 to find if it matches
foreach($packs as $k => $pack) {
    // use k+1 if you can't match the pack with itself
    for ($i = $k, $c = count ($packs); $i < $c; $i++) {
        //here we do the same as before to combine the packs as string, ex.: 2223
        $pack_zones = array_merge($pack['zones'], $packs[$i]['zones']);
        sort($pack_zones);
        $pack_zones = join('', $pack_zones);
        //if it's a substring of our product zones then we have a valid combination
        if (strpos($product_zones, $pack_zones) !== false) {
            $combinations[] = [$pack['name'], $packs[$i]['name']];
        }
    }
}

print_r($combinations);

result: 1,3 (22223) ; 1,4 (2233) ; 2,4 (22233) ; 3,3 (2233)

Upvotes: 1

Related Questions