How to list all possibilities from recursive tree? - php

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) {
}
}
}

Related

How to create multidimensional array unlimited depth array with parent and child came from single table

Im trying to create multi-dimesional array with unlimited depth.
I select the data from the database and check it if the field 'isArray' is true, meaning this column is a parent then I tried to make a loop to make it look for its child 'parent_id' => $row->id.
I'm expecting output like this.
array(
[0]=> array(
'id' => '29',
'section' => '',
'sorting' =>'',
'title' => 'POWERS OF THE BANKO SENTRAL',
'pdf_file' => '',
'content' => '',
'parent_id' => '0',
'isArray' => array(
[0] => array(
'id' => '30',
'section' => '001',
'sorting' => '',
'title' => 'Examination by the Bangko Sentral',
'pdf_file' => 'NRBSL CHRISTMAS PARTY RAFFLE WINNERS.pdf',
'parent_id' => '29',
'isArray' => 0,
),
[1] => array(
'id' => '31',
'section' => '002',
'sorting' => '',
'title' => 'Supervisory Enforcement',
'pdf_file' => 'APL-Form1.pdf'
'parent_id' => '29',
'isArray' => 0
)
),
),
[1]=> array(
[0] => array(
'id' => '32',
'section' => '',
'sorting' => '',
'title' => 'A. Risk Management',
'pdf_file' => '',
'content' => '',
'parent_id' => '0',
'isArray' => array(
[0] => array(
'id' => '33',
'section' => '911',
'sorting' => '',
'title' => 'RISK MANAGEMENT',
'pdf_file' => '',
'content' => '',
'parent_id' => '32',
'isArray' => array(
[0] => array(
'id' => '34',
'section' => 'ASDF',
'sorting' => '',
'title' => 'ASDFSDF',
'pdf_file' => '',
'content' => '',
'parent_id' => '33',
'isArray' = array()
)
)
)
)
)
)
)
And the data I get from the database is this
I came up with this code:
public function findParentsParent($result) {
global $subs;
foreach ($result as $row) {
$isArray = filter_var($row->isArray, FILTER_VALIDATE_BOOLEAN);
if ($isArray) {
$subs[][$row->parent_id] = $row;
$where = ['parent_id' => $row->id];
$result = $this->my_model->select_where('tbl_policies', $where, 'sorting, section');
if(!empty($result))
$this->findParentsParent($result);
//return array_reverse($subs);
} else {
$subs[] = $row;
}
}
return array_reverse($subs);
}
But I ended up with this array:
array(6) {
[0]=>
object(stdClass)#44 (11) {
["id"]=>
string(2) "30"
["section"]=>
string(3) "001"
["sorting"]=>
string(0) ""
["title"]=>
string(33) "Examination by the Bangko Sentral"
["pdf_file"]=>
string(41) "NRBSL CHRISTMAS PARTY RAFFLE WINNERS1.pdf"
["content"]=>
string(0) ""
["parent_id"]=>
string(2) "29"
["isArray"]=>
string(1) "0"
["uploaded_by"]=>
string(1) "6"
["created_at"]=>
string(19) "2022-03-03 11:46:06"
["updated_at"]=>
string(19) "2022-03-03 11:46:06"
}
[1]=>
object(stdClass)#43 (11) {
["id"]=>
string(2) "31"
["section"]=>
string(3) "002"
["sorting"]=>
NULL
["title"]=>
string(30) "Supervisory Enforcement Policy"
["pdf_file"]=>
string(13) "APL-Form1.pdf"
["content"]=>
string(0) ""
["parent_id"]=>
string(2) "29"
["isArray"]=>
string(1) "0"
["uploaded_by"]=>
string(1) "6"
["created_at"]=>
string(19) "2022-03-03 13:19:27"
["updated_at"]=>
string(19) "2022-03-03 13:19:27"
}
[2]=>
array(1) {
[0]=>
object(stdClass)#40 (11) {
["id"]=>
string(2) "29"
["section"]=>
string(0) ""
["sorting"]=>
string(0) ""
["title"]=>
string(28) "POWERS OF THE BANGKO SENTRAL"
["pdf_file"]=>
string(0) ""
["content"]=>
string(0) ""
["parent_id"]=>
string(1) "0"
["isArray"]=>
string(1) "1"
["uploaded_by"]=>
string(1) "6"
["created_at"]=>
string(19) "2022-03-03 11:45:25"
["updated_at"]=>
string(19) "2022-03-03 11:45:25"
}
}
[3]=>
array(1) {
[33]=>
object(stdClass)#42 (11) {
["id"]=>
string(2) "34"
["section"]=>
string(4) "ASDF"
["sorting"]=>
NULL
["title"]=>
string(7) "ASDFSDF"
["pdf_file"]=>
string(0) ""
["content"]=>
string(0) ""
["parent_id"]=>
string(2) "33"
["isArray"]=>
string(1) "1"
["uploaded_by"]=>
string(1) "6"
["created_at"]=>
string(19) "2022-03-04 09:29:37"
["updated_at"]=>
string(19) "2022-03-04 09:29:37"
}
}
[4]=>
array(1) {
[32]=>
object(stdClass)#41 (11) {
["id"]=>
string(2) "33"
["section"]=>
string(3) "911"
["sorting"]=>
NULL
["title"]=>
string(15) "RISK MANAGEMENT"
["pdf_file"]=>
string(0) ""
["content"]=>
string(0) ""
["parent_id"]=>
string(2) "32"
["isArray"]=>
string(1) "1"
["uploaded_by"]=>
string(1) "6"
["created_at"]=>
string(19) "2022-03-04 09:29:18"
["updated_at"]=>
string(19) "2022-03-04 09:29:18"
}
}
[5]=>
array(1) {
[0]=>
object(stdClass)#39 (11) {
["id"]=>
string(2) "32"
["section"]=>
NULL
["sorting"]=>
NULL
["title"]=>
string(18) "A. Risk Management"
["pdf_file"]=>
string(0) ""
["content"]=>
string(0) ""
["parent_id"]=>
string(1) "0"
["isArray"]=>
string(1) "1"
["uploaded_by"]=>
string(1) "6"
["created_at"]=>
string(19) "2022-03-04 09:28:41"
["updated_at"]=>
string(19) "2022-03-04 09:28:41"
}
}
}
Credits to Recursive function to generate multidimensional array from database result
I solved my problem with this code
public function buildTree(array $elements, $parentId = 0) {
$branch = array();
foreach ($elements as $element) {
if ($element['parent_id'] == $parentId) {
$children = $this->buildTree($elements, $element['id']);
$isArray = filter_var($element['isArray'], FILTER_VALIDATE_BOOLEAN);
if ($isArray) {
$element['isArray'] = $children;
}
$branch[] = $element;
}
}
return $branch;
}

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 references in uasort function

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)
}
}
}

sum values with given key in php? [duplicate]

This question already has answers here:
How to GROUP BY and SUM PHP Array? [duplicate]
(2 answers)
Closed 5 months ago.
given this array:
array(40) {
[0]=>
array(10) {
["item"]=>
string(5) "AABBCC"
["quants"]=>
string(1) "1"
}
[1]=>
array(10) {
["item"]=>
string(5) "AABBCC"
["quants"]=>
string(1) "1"
}
[2]=>
array(10) {
["item"]=>
string(5) "SLF02"
["quants"]=>
string(1) "1"
}
[3]=>
array(10) {
["item"]=>
string(5) "SLF02"
["quants"]=>
string(1) "3"
}
}
how without using a foreach do I end up with this output:
array(40) {
[0]=>
array(10) {
["item"]=>
string(5) "AABBCC"
["quants"]=>
string(1) "2"
}
[1]=>
array(10) {
["item"]=>
string(5) "SLF02"
["quants"]=>
string(1) "3"
}
}
are there any array_sum functions to do this with a multidimensional array like this in php?
This is a bad idea, but seemed like a fun challenge to do without a foreach:
$arr =
[
[
"item" =>"AABBCC",
"quants" => "1",
],
[
"item" => "AABBCC",
"quants" => "1",
],
[
"item" => "SLF02",
"quants" => "1",
],
[
"item" => "SLF02",
"quants" => "3",
]
];
$arr = array_values(call_user_func_array("array_merge", array_map(function($i) use ($arr) {
return [$i["item"] => ["item" => $i["item"], "quants" => array_reduce(
array_filter($arr, function($j) use ($i) {
return $j["item"] == $i["item"];
}), function($carry, $item) {
return $carry + $item["quants"];
})
]];
}, $arr)));
var_dump($arr);
/*
array(2) {
[0]=>
array(2) {
["item"]=>
string(6) "AABBCC"
["quants"]=>
int(2)
}
[1]=>
array(2) {
["item"]=>
string(5) "SLF02"
["quants"]=>
int(4)
}
}
*/
Here's my approach:
<?php
$array = array(
array('item'=>'AABBCC','quants'=>1),
array('item'=>'AABBCC','quants'=>1),
array('item'=>'SLF02','quants'=>1),
array('item'=>'SLF02','quants'=>3),
);
$summed_array = array();
foreach($array as $row){
$key = $row['item'];
if(!isset($summed_array[$key])){
$summed_array[$key] = array(
'item' => $row['item'],
'quants' => 0
);
}
$summed_array[$key]['quants'] += $row['quants'];
}
// turn the array back to a 0 based array
$summed_array = array_values($summed_array);
echo '<pre>',print_r($summed_array),'</pre>';

How to merge PHP multidimensional array keeping a unique key and separating with comma the other value

I have a multidimensional array and I want to make it matching the "unique key" value but merge the other key that has the same "unique key" value, it could be speared by comma, since my final output will be to use json_encode.
So for instance, if I have:
[0]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "123"
}
[1]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "124"
}
[2]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "126"
}
[3]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "129"
}
[4]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "130"
}
[5]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "102"
}
[6]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "193"
}
[7]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string(8) "156"
}
[8]=>
array(2) {
["label"]=>
string(2) "BG"
["value"]=>
string(8) "246"
}
[9]=>
array(2) {
["label"]=>
string(1) "C"
["value"]=>
string(8) "234"
}
[10]=>
array(2) {
["label"]=>
string(1) "C"
["value"]=>
string(8) "235"
}
[11]=>
array(2) {
["label"]=>
string(2) "CA"
["value"]=>
string(8) "345"
}
[12]=>
array(2) {
["label"]=>
string(2) "CA"
["value"]=>
string(8) "564"
}
And I want an output like:
[0]=>
array(2) {
["label"]=>
string(2) "AB"
["value"]=>
string "123,124,126,129,130,102,193,156“
}
[1]=>
array(2) {
["label"]=>
string(2) "BG"
["value"]=>
string "246"
}
[2]=>
array(2) {
["label"]=>
string(1) "C"
["value"]=>
string(8) "234,235,”
}
[3]=>
array(2) {
["label"]=>
string(2) "CA"
["value"]=>
string(8) "345,564,”
}
I am not sure how to do it, I've looked into array_merge_recursive and other similar solutions, but I did not got it, maybe I need to use implode.
You can use something like this:
$result = array();
foreach ($array as $arr) {
if (!isset($result[$arr['label']])) {
$result[$arr['label']] = $arr;
continue;
}
$result[$arr['label']]['value'] .= ',' . $arr['value'];
}
// if you really need numeric indexes use:
$result = array_values($result);
You can try
$array = array(
array(
'label' => "AB",
'value' => 123
),
array(
'label' => "AB",
'value' => 124
),
array(
'label' => "AB",
'value' => 125
),
array(
'label' => "C",
'value' => 126
),
array(
'label' => "C",
'value' => 127
),
array(
'label' => "C",
'value' => 127
),
);
$result = array();
foreach ($array as $el) {
$result[$el['label']] = array(
'label' => $el['label'],
'value' => implode( ',',
array_unique(
array_merge(
array_filter(
explode(',', $result[$el['label']]['value'])
),
array($el['value'])
)
)
)
);
}
echo "<pre>"; var_dump(array_values($result));

Categories