Organizing multi-dimensional array of inventory

Viewed 138

I need help organizing my inventory array. The structure is one big inventory array, with array of items inside. Per item array consists of the following: item, item_group, item_no and array sold. sold consists of inner arrays with dates and quantity. Now, I'm having trouble organizing it for my needed output. I'll give you guys sample of input and output. So please do check and it's very much appreciated.

Sample part of my $inventory array

Array
(
[0] => Array
    (
        [item] => NK
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 11
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 1
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 1
    )
[1] => Array
    (
        [item] => FL
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 7
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 2
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 2
    )
[2] => Array
    (
        [item] => AD
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 5
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 3
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 3
    )
[3] => Array
    (
        [item] => CV
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 4
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 6
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 4
    )
[4] => Array
    (
        [item] => NB
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 12
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 4
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 5
    )
[5] => Array
    (
        [item] => SP
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 4
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 6
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 6
    )
[6] => Array
    (
        [item] => WB
        [item_group] => 5
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 5
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 2
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 7
    )
[7] => Array
    (
        [item] => wny
        [item_group] => 12
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 4
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 6
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 8
    )
[8] => Array
    (
        [item] => bs
        [item_group] => 12
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 15
                        [date] => 2017-10-28
                    )
                [1] => Array
                    (
                        [quantity] => 2
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 9
    )
[9] => Array
    (
        [item] => st
        [item_group] => 12
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 16
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 10
    )
[10] => Array
    (
        [item] => ayhtdws
        [item_group] => 12
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 2
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 11
    )
[11] => Array
    (
        [item] => sif
        [item_group] => 12
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 3
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 12
    )
[12] => Array
    (
        [item] => bb
        [item_group] => 12
        [sold] => Array
            (
                [0] => Array
                    (
                        [quantity] => 6
                        [date] => 2017-10-29
                    )
            )
        [item_no] => 13
    )
)

From there, what I want to display is like this. Grouped by date ascending. And each item => quantity sold

Array
(
[0] => Array
    (
        [date] => 2017-10-28
        [NK] => 11
        [FL] => 7
        [AD] => 5
        [CV] => 4
        [NB] => 12
        [SP] => 4
        [WB] => 5
        [wny] => 4
        [bs] => 15
    )
[1] => Array
    (
        [date] => 2017-10-29
        [NK] => 1
        [FL] => 2
        [AD] => 3
        [CV] => 6
        [NB] => 4
        [SP] => 6
        [WB] => 2
        [wny] => 6
        [bs] => 2
        [st] => 16
        [ayhtdws] => 2
        [sif] => 3
        [bb] => 6
    )
)

I've spent almost 3 days figuring this out and up to this writing, I was only able to make it this far

$result = array();
$dates = array();
foreach ($inventory as $key => $item) {
    foreach ($item['sold'] as $k => $v) {
        array_push($dates, $v['date']);
    }
}
$dates = array_unique($dates);
foreach($dates as $key => $value) {
    array_push($result, array('date' => $value));
}
foreach ($dates as $rkey => $rvalue) {
    foreach ($inventory as $key => $item) {
        foreach ($item['sold'] as $k => $v) {
            if ($v['date'] = $result[$key]['date']) {
                array_push($result[$key][$item['item']] = $v['quantity']);
            }
        }
    }
}
return $result;

Which of course gives me this sad result

Array
(
[0] => Array
    (
        [date] => 2017-10-28
        [NK] => 1
    )
[1] => Array
    (
        [date] => 2017-10-29
        [FL] => 2
    )
)

And to make things worse, we have this rule about cyclomatic complexities that we should only have at most 3 loop/conditions and up to 3 nesting levels per loop/conditions. And the whole organizing should not have any user created functions.

Even if not following the rules, I wasn't able to figure it out for days. Sorry if problem is long. Please help :(

Update: var_export($inventory) output

array (
  0 => 
  array (
    'item' => 'NK',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '11',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '1',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '1',
  ),
  1 => 
  array (
    'item' => 'FL',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '7',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '2',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '2',
  ),
  2 => 
  array (
    'item' => 'AD',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '5',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '3',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '3',
  ),
  3 => 
  array (
    'item' => 'CV',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '4',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '6',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '4',
  ),
  4 => 
  array (
    'item' => 'NB',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '12',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '4',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '5',
  ),
  5 => 
  array (
    'item' => 'SP',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '4',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '6',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '6',
  ),
  6 => 
  array (
    'item' => 'WB',
    'item_group' => '5',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '5',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '2',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '7',
  ),
  7 => 
  array (
    'item' => 'wny',
    'item_group' => '12',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '4',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '6',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '8',
  ),
  8 => 
  array (
    'item' => 'bs',
    'item_group' => '12',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '15',
        'date' => '2017-10-28',
      ),
      1 => 
      array (
        'quantity' => '2',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '9',
  ),
  9 => 
  array (
    'item' => 'st',
    'item_group' => '12',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '16',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '10',
  ),
  10 => 
  array (
    'item' => 'ayhtdws',
    'item_group' => '12',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '2',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '11',
  ),
  11 => 
  array (
    'item' => 'sif',
    'item_group' => '12',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '3',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '12',
  ),
  12 => 
  array (
    'item' => 'bb',
    'item_group' => '12',
    'sold' => 
    array (
      0 => 
      array (
        'quantity' => '6',
        'date' => '2017-10-29',
      ),
    ),
    'item_no' => '13',
  ),
)
2 Answers

I don't know if this is more or less the same as Erwin's code, but I wrote this code 13 hours ago and had to wait for the array.

Edit; I have tested Erwin's code and it seems we have close to matching code. He makes one loop more to get the date in there but it's more or less the same.

I loop the array and the subarray sold.
I make the new array key the date example:

Echo $new['2017-10-28']['nk']; // 11

And if the date key is not set already I create it.

Once the loop is done I use array_values to remove the date keys making the array look like:

Echo $new[0]['nk']; // 11

The code:

$new =[];

Foreach($inventory as $sub){
    Foreach($sub["sold"] as $sold){
        If (!isset($new[$sold["date"]]["date"])) $new[$sold["date"]]["date"] = $sold["date"];
        $new[$sold["date"]][$sub["item"]] =  $sold["quantity"];
    }
}
$new = array_values($new);
Var_dump($new);

https://3v4l.org/mGJSX

I've run through some tests and workarounds and come up with this solution. I've managed to do it by using ksort(), array_values()and array_key_exists(). I used the date first as an array key to contain all items sold on that date. Then, move it inside the array after gathering all items, then renumbered the array. Further explanation is given through code comments

// result array
$result = array();

// Loop for each item on inventory
foreach ($inventory as $inv) {
    // Loop for each sold array
    foreach ($inv['sold'] as $item) {
        // date sold
        $date = $item['date'];
        // Check if date already exist in result array as key
        // If not, Create new array with key equal to date and push to result array
        if (!array_key_exists($date, $result)) {
            $result[$date] = array();
        }
        // Add array of item  =>  quantity to corresponding date array inside result array
        $result[$date][$inv['item']] = $item['quantity'];
    }
}
// From here you already have each item  =>  quantity sold inside each date array
// e.g. $result = array( '2017-10-28'  =>  array('NK'  =>  '11', 'FL'  =>  '7', ...) );

// Sort keys which are dates ascending
ksort($result);
// Loop to results and set
foreach ($result as $key  =>  $value) {
    $result[$key]['date'] = $key;
}
// Renumber Keys
$result = array_values($result);

// Print result
echo '<pre>';
print_r($result);

Output

Array
(
[0] => Array
    (
        [NK] => 11
        [FL] => 7
        [AD] => 5
        [CV] => 4
        [NB] => 12
        [SP] => 4
        [WB] => 5
        [wny] => 4
        [bs] => 15
        [date] => 2017-10-28
    )

[1] => Array
    (
        [NK] => 1
        [FL] => 2
        [AD] => 3
        [CV] => 6
        [NB] => 4
        [SP] => 6
        [WB] => 2
        [wny] => 6
        [bs] => 2
        [st] => 16
        [ayhtdws] => 2
        [sif] => 3
        [bb] => 6
        [date] => 2017-10-29
    )

)
Related