PHP references in uasort function - php

I have
$products = array(
"product1" => [
"a" => ["total" => 1],
"b" => ["total" => 3],
"c" => ["total" => 2],
],
"product2" => [
"d" => ["total" => 3],
"f" => ["total" => 2],
"e" => ["total" => 1],
],
"product3" => [
"g" => ["total" => 3]
],
);
theses are my products and my stocks for each warehouses (warehouse a has 1 item of product1...)
I want to sort each warehouse by stock for each products.
I've done that :
foreach ($products as &$stocks) {
uasort($stocks, function($elmt1, $elmt2) {
return $elmt2["total"] - $elmt1["total"];
});
}
where I print my new array :
array(3) {
["product1"]=>
array(3) {
["b"]=>
array(1) {
["total"]=>
int(3)
}
["c"]=>
array(1) {
["total"]=>
int(2)
}
["a"]=>
array(1) {
["total"]=>
int(1)
}
}
["product2"]=>
array(3) {
["d"]=>
array(1) {
["total"]=>
int(3)
}
["f"]=>
array(1) {
["total"]=>
int(2)
}
["e"]=>
array(1) {
["total"]=>
int(1)
}
}
["product3"]=>
&array(1) {
["g"]=>
array(1) {
["total"]=>
int(3)
}
}
}
It did my job but when I get a closer look I can see the "&" char in only one of the arrays.
Why ?

Due to the fact that $item - a reference to the last element of the array.
You can do this trick:
$array = ['a', 'b', 'c'];
foreach ($array as &$item) {
}
foreach ($array as $item) {
$item = 1;
}
var_dump($array);
Output:
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
&int(1)
}
It's not terrible, as long as you do not start to use $item.
It is better to make a job with reference in different function
$array = ['a', 'b', 'c'];
$test = function () use (&$array) {
foreach ($array as &$item) {
}
};
$test();
var_dump($array);
Output:
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
Or try this:
$products = array(
"product1" => [
"a" => ["total" => 1],
"b" => ["total" => 3],
"c" => ["total" => 2],
],
"product2" => [
"d" => ["total" => 3],
"f" => ["total" => 2],
"e" => ["total" => 1],
],
"product3" => [
"g" => ["total" => 3]
],
);
foreach ($products as $key=>$stocks) {
uasort($products[$key], function($elmt1, $elmt2) {
return $elmt2["total"] - $elmt1["total"];
});
}
var_dump($products);
Output:
array(3) {
["product1"]=>
array(3) {
["b"]=>
array(1) {
["total"]=>
int(3)
}
["c"]=>
array(1) {
["total"]=>
int(2)
}
["a"]=>
array(1) {
["total"]=>
int(1)
}
}
["product2"]=>
array(3) {
["d"]=>
array(1) {
["total"]=>
int(3)
}
["f"]=>
array(1) {
["total"]=>
int(2)
}
["e"]=>
array(1) {
["total"]=>
int(1)
}
}
["product3"]=>
array(1) {
["g"]=>
array(1) {
["total"]=>
int(3)
}
}
}

Related

How to list all possibilities from recursive tree?

I've got this initial data:
$h = [
'id' => 'h',
'name' => 'H',
'config' => [],
];
$g = [
'id' => 'g',
'name' => 'G',
'config' => [],
];
$f = [
'id' => 'f',
'name' => 'F',
'config' => [
[
['id' => $g['id'], 'quantity' => 1],
],
[
['id' => $h['id'], 'quantity' => 2],
],
],
];
$e = [
'id' => 'e',
'name' => 'E',
'config' => [],
];
$d = [
'id' => 'd',
'name' => 'D',
'config' => [
[
['id' => $e['id'], 'quantity' => 1],
['id' => $f['id'], 'quantity' => 3],
],
],
];
$c = [
'id' => 'c',
'name' => 'C',
'config' => [
[
['id' => $f['id'], 'quantity' => 1],
],
[
['id' => $e['id'], 'quantity' => 1],
],
],
];
$b = [
'id' => 'b',
'name' => 'B',
'config' => [
[
['id' => $c['id'], 'quantity' => 1],
],
],
];
$a = [
'id' => 'a',
'name' => 'A',
'config' => [
[
['id' => $d['id'], 'quantity' => 1],
],
[
['id' => $b['id'], 'quantity' => 1],
],
],
];
I will explain how "config" works:
it's an array of possibilities (OR) => for example from $c we can have $f OR $e
inside these possibilities there's an array of AND =>, for example, from $d we have only one possibility with $e AND $f
when the config is empty, it's a leaf so we can stop
and the tricky part (I think) is that we can have quantity inside each config which means from $f we can have $g once OR $h twice and from $d we have $e once AND $f 3 times
What I want to achieve with my algorithm is having output like this :
$possibilities = [
[
[
'id' => 'a',
...
],
[
'id' => 'b',
'parent' => 'a',
...
],
[
'id' => 'c',
'parent' => 'b',
...
],
[
'id' => 'f',
'parent' => 'c'
]
],
[
[
'id' => 'a',
...
],
[
'id' => 'b',
'parent' => 'a',
...
],
[
'id' => 'c',
'parent' => 'b',
...
],
[
'id' => 'e',
'parent' => 'c'
]
],
[
[
'id' => 'a',
...
],
[
'id' => 'd',
'parent' => 'a',
...
],
[
'id' => 'e',
'parent' => 'd',
...
],
[
'id' => 'f-1',
'parent' => 'd',
...
],
[
'id' => 'f-2',
'parent' => 'd',
...
],
[
'id' => 'f-3',
'parent' => 'd',
...
],
[
'id' => 'g',
'parent' => 'f-1',
...
],
[
'id' => 'g',
'parent' => 'f-2',
...
],
[
'id' => 'g',
'parent' => 'f-3',
...
]
],
...
];
So I want to extract and list any possibility and having the parent node (including its number in case quantity > 1)
So far I've tried something like this :
global $datas;
$datas = compact($a, $b, $c, $d, $e, $f, $g, $h);
function formatTree($tree)
{
if (empty($tree['config'])) {
return [$tree];
}
$config = $tree['config'];
unset($tree['config']);
$tree2 = [$tree];
foreach ($config as $item) {
$sub = formatTree($item);
$tree2 = array_merge($tree2, $sub);
}
return $tree2;
}
function preparePossibilities($item)
{
$possibilities = [];
if (empty($item['config'])) {
return [$item];
}
$config = $item['config'];
unset($item['config']);
foreach ($config as $or) {
$finalOr = [];
foreach ($or as $and) {
for ($i = 0; $i < ($and['quantity'] ?? 1); $i++) {
$finalOr[] = $and;
}
}
$item['config'] = $finalOr;
$possibilities[] = $item;
}
return $possibilities;
}
function are_same($trees)
{
$id = null;
foreach ($trees as $tree) {
$oldId = $id;
$id = $tree[0]['id'];
if (isset($oldId) && $oldId !== $id) {
return false;
}
}
return true;
}
function getAllTrees($id)
{
global $datas;
$data = current(array_filter($datas, static function ($d) use ($id) {
return $d['id'] === $id;
}));
$multiplePossibilities = preparePossibilities($data);
$allTrees = [];
foreach ($multiplePossibilities as $possibility) {
if (empty($possibility['config'])) {
return [$possibility];
}
$config = $possibility['config'];
unset($possibility['config']);
$trees = [];
foreach ($config as $i => $and) {
$subTrees = getAllTrees($and['id']);
foreach ($subTrees as $subTree) {
$trees[$i][] = $subTree;
}
}
$trees = array_values($trees);
if (count($trees) === 1) {
foreach ($trees as $tree) {
foreach ($tree as $t) {
$newP = $possibility;
$newP['config'] = [];
$newP['config'][] = $t;
$allTrees[] = $newP;
}
}
} elseif (are_same($trees)) {
$newP = $possibility;
$newP['config'] = $trees;
$allTrees[] = $newP;
} else {
$newP = $possibility;
$newP['config'] = [];
foreach ($trees as $tree) {
if (count($tree) === 1) {
$newP['config'][] = $tree[0];
} else {
foreach ($tree as $t) {
$p3 = $newP;
$p3['config'][] = $t;
$allTrees[] = $p3;
}
}
}
}
}
return $allTrees;
}
foreach (getAllTrees('a') as $tree) {
var_dump(formatTree($tree));
}
And the output is :
array(5) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "d"
["name"]=>
string(1) "D"
}
[2]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(3) {
["id"]=>
string(1) "g"
["name"]=>
string(1) "G"
["config"]=>
array(0) {
}
}
}
array(6) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "d"
["name"]=>
string(1) "D"
}
[2]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
[5]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
}
array(5) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "d"
["name"]=>
string(1) "D"
}
[2]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(3) {
["id"]=>
string(1) "g"
["name"]=>
string(1) "G"
["config"]=>
array(0) {
}
}
}
array(6) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "d"
["name"]=>
string(1) "D"
}
[2]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
[5]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
}
array(5) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "d"
["name"]=>
string(1) "D"
}
[2]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(3) {
["id"]=>
string(1) "g"
["name"]=>
string(1) "G"
["config"]=>
array(0) {
}
}
}
array(6) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "d"
["name"]=>
string(1) "D"
}
[2]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
[5]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
}
array(5) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "b"
["name"]=>
string(1) "B"
}
[2]=>
array(2) {
["id"]=>
string(1) "c"
["name"]=>
string(1) "C"
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(3) {
["id"]=>
string(1) "g"
["name"]=>
string(1) "G"
["config"]=>
array(0) {
}
}
}
array(6) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "b"
["name"]=>
string(1) "B"
}
[2]=>
array(2) {
["id"]=>
string(1) "c"
["name"]=>
string(1) "C"
}
[3]=>
array(2) {
["id"]=>
string(1) "f"
["name"]=>
string(1) "F"
}
[4]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
[5]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "h"
["name"]=>
string(1) "H"
["config"]=>
array(0) {
}
}
}
}
array(4) {
[0]=>
array(2) {
["id"]=>
string(1) "a"
["name"]=>
string(1) "A"
}
[1]=>
array(2) {
["id"]=>
string(1) "b"
["name"]=>
string(1) "B"
}
[2]=>
array(2) {
["id"]=>
string(1) "c"
["name"]=>
string(1) "C"
}
[3]=>
array(3) {
["id"]=>
string(1) "e"
["name"]=>
string(1) "E"
["config"]=>
array(0) {
}
}
}

How to add multidimensional array to an element of a multidimensional array

I am trying to add a multidimensional array somewhere inside another multidimensional array. I have this code example to explain what I try to do and what goes wrong:
$a_base = [
'wop' =>
[
'tik' =>
[
'a' => 190,
'b' => 323,
'c' => 342
],
'tak' =>
[
'a' => 142,
'b' => 654,
'c' => 785
]
],
'wap' =>
[
'top' =>
[
'a' => 564,
'b' => 667,
'c' => 968
],
'top' =>
[
'a' => 603,
'b' => 694,
'c' => 102
]
]
];
$a_addon = [
'tok' =>
[
'a' => 883,
'b' => 993,
'c' => 878
]
];
array_push($a_base['wop'], $a_addon);
var_dump($a_base);
The result is this:
array(2) {
["wop"]=>
array(3) {
["tik"]=>
array(3) {
["a"]=>
int(190)
["b"]=>
int(323)
["c"]=>
int(342)
}
["tak"]=>
array(3) {
["a"]=>
int(142)
["b"]=>
int(654)
["c"]=>
int(785)
}
[0]=>
array(1) {
["tok"]=>
array(3) {
["a"]=>
int(883)
["b"]=>
int(993)
["c"]=>
int(878)
}
}
}
["wap"]=>
array(1) {
["top"]=>
array(3) {
["a"]=>
int(603)
["b"]=>
int(694)
["c"]=>
int(102)
}
}
}
But what I need is this (without the [0]=> array(1) {...}):
array(2) {
["wop"]=>
array(3) {
["tik"]=>
array(3) {
["a"]=>
int(190)
["b"]=>
int(323)
["c"]=>
int(342)
}
["tak"]=>
array(3) {
["a"]=>
int(142)
["b"]=>
int(654)
["c"]=>
int(785)
}
["tok"]=>
array(3) {
["a"]=>
int(883)
["b"]=>
int(993)
["c"]=>
int(878)
}
}
["wap"]=>
array(1) {
["top"]=>
array(3) {
["a"]=>
int(603)
["b"]=>
int(694)
["c"]=>
int(102)
}
}
}
I have tried other functions like array_combine et cetera, but without success. Can anyone help me how to do this?
An array union will work perfectly as a functionless array merging technique on your associative arrays.
Code: (Demo)
$a_base['wop'] += $a_addon;
Use array_merge()
$a_base['wop'] = array_merge($a_base['wop'], $a_addon);

Multiply two arrays with different length in PHP?

I have a dynamic array:
$variants = [
'color' => ['Blue', 'Red', 'Pink'],
'size' => ['X', 'S'],
... (maybe more elements like above or not)
];
I expect this:
$result = [
0 => ['color' => 'Blue', 'size' => 'X'],
1 => ['color' => 'Blue', 'size' => 'S'],
2 => ['color' => 'Red', 'size' => 'X'],
3 => ['color' => 'Red', 'size' => 'S'],
4 => ['color' => 'Pink', 'size' => 'X'],
5 => ['color' => 'Pink', 'size' => 'S']
];
Result is the multiplying of all array lengths. I've searched but not found the solution yet. Hope anyone could help. Many thanks!
This is a bit tricky, you need a preparation and an aggregation step for this. But it is possible without falling back to recursion:
<?php
$variants = [
'color' => ['Blue', 'Red', 'Pink'],
'size' => ['X', 'S'],
'weight' => [150, 250]
];
$result = [];
foreach ($variants as $key => $set) {
foreach ($set as $entry) {
$result[] = [$key => $entry];
}
break;
}
array_shift($variants);
foreach($variants as $setKey => $set) {
$buffer = $result;
$result = [];
foreach ($set as $entry) {
foreach ($buffer as $buf) {
$result[] = array_merge($buf, [$setKey => $entry]);
}
}
}
var_dump($result);
The output of that is:
array(12) {
[0]=>
array(3) {
["color"]=>
string(4) "Blue"
["size"]=>
string(1) "X"
["weight"]=>
int(150)
}
[1]=>
array(3) {
["color"]=>
string(3) "Red"
["size"]=>
string(1) "X"
["weight"]=>
int(150)
}
[2]=>
array(3) {
["color"]=>
string(4) "Pink"
["size"]=>
string(1) "X"
["weight"]=>
int(150)
}
[3]=>
array(3) {
["color"]=>
string(4) "Blue"
["size"]=>
string(1) "S"
["weight"]=>
int(150)
}
[4]=>
array(3) {
["color"]=>
string(3) "Red"
["size"]=>
string(1) "S"
["weight"]=>
int(150)
}
[5]=>
array(3) {
["color"]=>
string(4) "Pink"
["size"]=>
string(1) "S"
["weight"]=>
int(150)
}
[6]=>
array(3) {
["color"]=>
string(4) "Blue"
["size"]=>
string(1) "X"
["weight"]=>
int(250)
}
[7]=>
array(3) {
["color"]=>
string(3) "Red"
["size"]=>
string(1) "X"
["weight"]=>
int(250)
}
[8]=>
array(3) {
["color"]=>
string(4) "Pink"
["size"]=>
string(1) "X"
["weight"]=>
int(250)
}
[9]=>
array(3) {
["color"]=>
string(4) "Blue"
["size"]=>
string(1) "S"
["weight"]=>
int(250)
}
[10]=>
array(3) {
["color"]=>
string(3) "Red"
["size"]=>
string(1) "S"
["weight"]=>
int(250)
}
[11]=>
array(3) {
["color"]=>
string(4) "Pink"
["size"]=>
string(1) "S"
["weight"]=>
int(250)
}
}
A function that makes what you want
function get_combinations($arrays) {
$result = array(array());
foreach ($arrays as $property => $property_values) {
$tmp = array();
foreach ($result as $result_item) {
foreach ($property_values as $property_value) {
$tmp[] = array_merge($result_item, array($property => $property_value));
}
}
$result = $tmp;
}
return $result;
}
$variants = [
'color' => ['Blue', 'Red', 'Pink'],
'size' => ['X', 'S']
];
$result = get_combinations($variants);
The result will be like you want it.

PHP Array Goup using date with multiple keys and assign Sum of keys

I'm wring a PHP script to group some payment info using date. part of original array is like this.
array(50) {
[0]=>
array(2) {
["Datum"]=>
string(10) "2016-07-07"
["C"]=>
int(1)
}
[1]=>
array(2) {
["Datum"]=>
string(10) "2016-07-07"
["C"]=>
int(1)
}
[2]=>
array(2) {
["Datum"]=>
string(10) "2016-07-07"
["Paypal"]=>
int(1)
}
[3]=>
array(2) {
["Datum"]=>
string(10) "2016-07-07"
["Bank"]=>
int(1)
}
[4]=>
array(2) {
["Datum"]=>
string(10) "2016-07-12"
["C"]=>
int(1)
}
[5]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[6]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[7]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["Afterpay"]=>
int(1)
}
[8]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[9]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[10]=>
array(2) {
["Datum"]=>
string(10) "2016-06-12"
["C"]=>
int(1)
}
[11]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[12]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[13]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[14]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[15]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[16]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[17]=>
array(2) {
["Datum"]=>
string(10) "2016-06-13"
["C"]=>
int(1)
}
[18]=>
array(2) {
["Datum"]=>
string(10) "2016-06-14"
["Afterpay"]=>
int(1)
}
[19]=>
array(2) {
["Datum"]=>
string(10) "2016-06-14"
["C"]=>
int(1)
}
}
I wrote some codes to group those by date. here is my code
//$shipment - this is the original array
$array1 = array('C' => null, 'afterpay' => null,'paypal' => null, 'Bank' => null, 'Ideal' => null);
$array2 = array();
array_walk($shipment, function ($v) use (&$array2, $array1) {
$a = $v['Datum'];
if (!isset($array2[$a])) {
$array2[$a] = $array1;
}
unset($v['Datum']);
$array2[$a] = array_merge($array2[$a], $v);
});
Output after grouping
Array
(
[2016-07-07] => Array
(
[C] => 1
[afterpay] =>
[paypal] =>
[Bank] => 1
[Ideal] =>
[Paypal] => 1
)
[2016-07-12] => Array
(
[C] => 1
[afterpay] =>
[paypal] =>
[Bank] =>
[Ideal] =>
)
[2016-06-13] => Array
(
[C] => 1
[afterpay] =>
[paypal] =>
[Bank] =>
[Ideal] =>
[Afterpay] => 1
)
[2016-06-12] => Array
(
[C] => 1
[afterpay] =>
[paypal] =>
[Bank] =>
[Ideal] =>
)
[2016-06-14] => Array
(
[C] => 1
[afterpay] =>
[paypal] =>
[Bank] =>
[Ideal] =>
[Afterpay] => 1
)
)
but it's difficult me to find a way to count the payment method numbers and assign it
Example for 2016-07-07 array should be C= 2,Paypal = 1, Bank = 1
[2016-07-07] => Array
(
[C] => 2
[afterpay] =>
[paypal] =>
[Bank] => 1
[Ideal] =>
[Paypal] => 1
)
can someone help me to add some code for get sum of payment methods and assign, thanks a lot
This happens because array_merge override the data if 2 keys are the same - what you need is to add all fields.
First, change $array1 with init field as 0 instead of null.
Second, in your array_walk, replace $array2[$a] = array_merge($array2[$a], $v); with:
foreach($v as $k => $v)
$array2[$a][$k] += $v;
This way you will add up each category
We need to increase Payment Method instead of merge array, to prevent overwrite old value.
Below code working for me
<?php
$shipment = [
[
'Datum' => '2016-07-07',
'C' => 1,
],
[
'Datum' => '2016-07-07',
'C' => 1,
],
[
'Datum' => '2016-07-07',
'Paypal' => 1,
],
[
'Datum' => '2016-07-07',
'Bank' => 1,
],
[
'Datum' => '2016-07-12',
'Bank' => 1,
],
];
$template = ['C' => 0, 'Afterpay' => 0, 'Paypal' => 0, 'Bank' => 0, 'Ideal' => 0];
$result = [];
array_walk($shipment, function ($v) use (&$result, $template) {
// Init by Datum if it is not in array
$date = $v['Datum'];
if (!isset($result[$date])) {
$result[$date] = $template;
}
// Unset Datum to get final payment method only
unset($v['Datum']);
$itemKey = array_keys($v)[0];
// Increase number
$result[$date][$itemKey] += $v[$itemKey];
});
// Dump result
var_dump($result);

PHP indexed array to nested associative array

I need to convert simple array to nested array according to specific rules. I've achived it but I'm looking for better solution.
SIMPLE:
array(4) {
[0]=>
array(2) {
["id"]=>
string(2) "11"
["type"]=>
int(3)
}
[1]=>
array(2) {
["id"]=>
string(2) "10"
["type"]=>
int(2)
}
[2]=>
array(2) {
["id"]=>
string(1) "1"
["type"]=>
int(1)
}
[3]=>
array(2) {
["id"]=>
string(1) "0"
["type"]=>
int(1)
}
}
EXPECTED EFFECT:
array(1) {
[0]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[1]=>
array(2) {
["type"]=>
int(1)
["child"]=>
array(1) {
[10]=>
array(2) {
["type"]=>
int(2)
["child"]=>
array(1) {
[11]=>
array(2) {
["type"]=>
int(3)
["child"]=>
array(0) {
}
}
}
}
}
}
}
}
}
MY SOLUTION (not very satisfying):
$nestedArray = [];
foreach ($simpleArray as $item)
{
if (!empty($nestedArray))
{
$array = $nestedArray;
reset($array);
$firstKey = key($array);
}
$nestedArray[$item['id']]['child'] = $nestedArray;
$nestedArray[$item['id']]['type'] = $item['type'];
if (!empty($firstKey))
{
unset($nestedArray[$firstKey]);
}
}
As I said, I'm looking for more elegant way to achieve that. Rule are very simply: every next item is child of previous.
You could use recursion:
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
With your example input, it would look like this:
$simpleArray = [
["id" => "11", "type" => 3],
["id" => "10", "type" => 2],
["id" => "1", "type" => 1],
["id" => "0", "type" => 1]
];
function nest($arr) {
return count($arr) ? ["type" => array_pop($arr)["type"], "child" => nest($arr)] : [];
}
$nested = nest($simpleArray));
$nested will have the following value:
[
"type" => 1,
"child" => [
"type" => 1,
"child" => [
"type" => 2,
"child" => [
"type" => 3,
"child" => []
]
]
]
]

Categories