0

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:

  • Combination 1:
    • Pack 1 (when Pack zones are in Products Zones, add pack to combination and remove products from array)
    • Pack 1
  • Combination 2:
    • Pack 1
    • Pack 3
  • Combination 3:
    • Pack 1
    • Pack 4
  • Combination 4:
    • Pack 2
    • Pack 4
  • Combination 5:
    • Pack 2
    • Pack 2
    • Pack 4

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;
}
7
  • 2
    The arrays in your first snippet are not valid. Keys have to be unique, and you have multiple entries with the same key in the same array. e.g array('zone' => 2, 'zone' => 2) Commented Nov 5, 2020 at 17:21
  • I didn't get the logic here. Why Combination 4 are expected, if Pack 2 and 4 have different zones? Commented Nov 5, 2020 at 17:25
  • @GrumpyCrouton Yes, changed! sorry Commented Nov 5, 2020 at 17:28
  • @FelippeDuarte, product zones are 2, 3, 2, 2, 3; Pack 2 zones are 2, 2, 2 and Pack 4 zones are 3, 3; If we join Pack2 zones and Pack3 zones are the same combination that we have in Product zones 2, 2, 2, 3, 3 Commented Nov 5, 2020 at 17:29
  • 1
    Why pack 1 + pack 1 is a valid combination, as it have four "2's" (2,2,2,2) and the products only have three "2's" (2,2,2,3,3)? Commented Nov 5, 2020 at 17:39

1 Answer 1

1

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)

Sign up to request clarification or add additional context in comments.

1 Comment

Thx! Let me adapt what you send me to my array structure and I'll tell you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.