Surinder Singh
Surinder Singh

Reputation: 23

PHP Array function to compare and merge values

Appreciate your time!

After reviewing several 'Compare and Merge' threads, finally, I am going to request someone to help with this very specific scenario.

$input = array(
  [ 2616 ] => array(
    [ 9878767654 ] => array(
      [ 987987987 ] => 987987987, 
      [ 987987986 ] => 987987986,
    ),
  ), 
  [ 2618 ] => array(
    [ 9878767654 ] => array(
      [ 987987987 ] => 987987987,
    ),

  ), 
  [ 'tmp-9878767654' ] => array(
    [ 9878767654 ] => array(
      [ 987987985 ] => 987987985, 
      [ 987987987 ] => 987987987,
    ),

  ), 
  [ 'tmp-9878767655' ] => array(
    [ 9878767655 ] => array(
      [ 987987975 ] => 987987975,
    ),
  ),
);

$desired_output = array(
  [ 2616 ] => array(
    [ 9878767654 ] => array(
      [ 987987987 ] => 987987987, 
      [ 987987986 ] => 987987986,
      [ 987987985 ] => 987987985,
    ),
  ),
  [ 2618 ] => array(
    [ 9878767654 ] => array(
      [ 987987987 ] => 987987987, 
      [ 987987986 ] => 987987986,
      [ 987987985 ] => 987987985,
    ),
  ),
  [ 'tmp-9878767655' ] => array(
    [ 9878767655 ] => array(
      [ 987987975 ] => 987987975,
    ),
  ),
);

This is the inventory of products (listed by Product ID and Model ID) by Store ID. I want to merge the Model ID values WHERE the product id is the same FROM the array with store-ID starting with 'tmp-'. If product ID is not matched then I want that array to stay as it is. I hope I am making some sense.

Please help.

Upvotes: 1

Views: 57

Answers (1)

Jeroen van der Laan
Jeroen van der Laan

Reputation: 724

Here is a snippet to solve the specific problem posed by your example:

$temporaryStores = [];
$prefix = 'tmp-';
$prefixLength = strlen($prefix);

// extract the temporary store structures
foreach ($input as $storeId => $store) {
    if (is_string($storeId) && strpos($storeId, $prefix) === 0) {
        $productId = (int) substr($storeId, $prefixLength);
        $temporaryStores[$productId] = $store;
        unset($input[$storeId]);
    }
}

// merge matching temporary store structures into the actual ones
$mergedProductIds = [];
foreach ($temporaryStores as $temporaryProductId => $temporaryModels) {
    $temporaryModels = reset($temporaryModels); // Incompatible array structure
    foreach ($input as $storeId => $store) {
        foreach ($store as $productId => $models) {
            if ($productId === $temporaryProductId) {
                $modelsIds = array_merge($temporaryModels, $models);
                $modelsIds = array_unique($modelsIds);
                $input[$storeId][$productId] = $modelsIds;
                $mergedProductIds[] = $temporaryProductId;
                unset($temporaryStores[$temporaryProductId]);
            }
        }
    }
}

// append leftover temporary store structures to the result
foreach ($temporaryStores as $temporaryProductId => $temporaryModels) {
    if (!in_array($temporaryProductId, $mergedProductIds, true)) {
        $input[$prefix . $temporaryProductId] = $temporaryModels;
    }
}

var_dump($input);

This snippet might work for you or not. Either way, I strongly suggest you refactor this code into using a more object oriented design. Where it is made obvious what each value/structure represents, and validation can occur in isolation.

Now you are left having to deal with incompatible array structures that visually look like an incomprehensible mess.

Upvotes: 1

Related Questions