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.
Related
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) {
}
}
}
Don't know this question is asked before or not, cannot find after lot of searching.
My array looks like this,
array(3) {
[0]=>
array(2) {
[0]=>
array(1) {
["userId"]=>
string(3) "421"
}
[1]=>
array(1) {
["userId"]=>
string(3) "329"
}
}
[1]=>
array(1) {
[0]=>
array(1) {
["userId"]=>
string(3) "329"
}
}
[4]=>
array(2) {
[0]=>
array(1) {
["userId"]=>
string(3) "329"
}
[1]=>
array(1) {
["userId"]=>
string(3) "421"
}
}
}
What I want is,
array(1) {
[0]=>
array(5) {
[0]=>
array(1) {
["userId"]=>
string(3) "421"
}
[1]=>
array(1) {
["userId"]=>
string(3) "329"
}
[2]=>
array(1) {
["userId"]=>
string(3) "329"
}
[3]=>
array(1) {
["userId"]=>
string(3) "329"
}
[4]=>
array(1) {
["userId"]=>
string(3) "421"
}
}
}
I have tried with array_merge, array_combine and a lot of foreach() loops. But didn't get luck for desired output.
Don't know how to do this. Please help.
You can flatten your array like this:
$arr = array(array(['user' => 1], ['user' => 2]), ['user' => 3]);
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach($iterator as $val) {
$flattened_arr[0][] = $val;
}
var_dump($flattened_arr);
UPDATE: If you don't want to use RecursiveIteratorIterator, the you can also do it like this using array_walk_recursive():
$non_flat_arr = array(array(['user' => 1], ['user' => 2]), ['user' => 3]);
$objTmp = (object) array('flat_arr' => array());
array_walk_recursive($non_flat_arr, create_function('&$v, $k, &$t', '$t->flat_arr[] = $v;'), $objTmp);
var_dump([ 0 => $objTmp->flat_arr]);
This will give you the output as:
array:1 [
0 => array:3 [
0 => 1
1 => 2
2 => 3
]
]
Hope this helps!
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)
}
}
}
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));
I'm trying to create a multidimensional array from a form post. This is the dump from that post:
array(8) {
["check"]=>
int(1)
["option_page"]=>
string(19) "content_boxes_group"
["action"]=>
string(6) "update"
["_wpnonce"]=>
string(10) "0adb157142"
["_wp_http_referer"]=>
string(39) "/wp-admin/themes.php?page=home-settings"
["title"]=>
array(3) {
[1]=>
string(9) "Downloads"
[2]=>
string(7) "Columns"
[3]=>
string(4) "Apps"
}
["id"]=>
array(3) {
[1]=>
string(21) "k2-settings-downloads"
[2]=>
string(19) "k2-settings-columns"
[3]=>
string(16) "k2-settings-apps"
}
["order"]=>
array(3) {
[1]=>
string(1) "1"
[2]=>
string(1) "2"
[3]=>
string(1) "3"
}
}
I'm trying to make it look like this:
array(
array('title' => 'Downloads', 'id' => 'k2-settings-downloads', 'order' => '1'),
array('title' => 'Columns', 'id' => 'k2-settings-columns', 'order' => '2'),
array('title' => 'Apps', 'id' => 'k2-settings-apps', 'order' => '3')
);
How can I do this?
something like this?
$post = $_POST['your_array'];
$output = array();
$titles = $post['title'];
$ids = $post['id'];
$orders = $post['order'];
foreach($titles as $id => $title){
$output[] = array("title"=>$title,"id"=>$ids[$id],'order'=>$orders[$id]);
}