I have small difficulties to convert an array as I want, need some help from pros.
I have an array like that :
$inputs = array(
'size' => array(
's' => 's',
'm' => 'm',
'l' => 'l',
),
'color' => array(
'red' => 'red',
'blue' => 'blue',
),
'option' => 'option 1',
);
From this values, I need to create an array that combine all possibilities, like that :
$possibilities = array(
0 => array('size' => 's', 'color' => 'red', 'option' => 'option 1'),
1 => array('size' => 'm', 'color' => 'red', 'option' => 'option 1'),
2 => array('size' => 'l', 'color' => 'red', 'option' => 'option 1'),
3 => array('size' => 's', 'color' => 'blue', 'option' => 'option 1'),
4 => array('size' => 'm', 'color' => 'blue', 'option' => 'option 1'),
5 => array('size' => 'l', 'color' => 'blue', 'option' => 'option 1'),
);
I precise that I'm on laravel so I can use the collection methods, but even with this helpers methods, I can't find a way to obtain the $possibilities array I want.
The original array is dynamic (can have more options with different label names), so I need something that is able to work no matter the size of the array neither the name of the labels.
Please try this, I hope it'll help you.
<?php
$inputs = array(
'size' => array(
's' => 's',
'm' => 'm',
'l' => 'l',
),
'color' => array(
'red' => 'red',
'blue' => 'blue',
),
'option' => 'option 1',
);
$combinations = [[]];
$length = count($inputs);
foreach (array_keys($inputs) as $key) {
$tmp = [];
foreach ($combinations as $v1) {
if (is_array($inputs[$key])) {
foreach ($inputs[$key] as $v2) {
$tmp[] = array_merge($v1, [$key => $v2]);
}
} else {
$tmp[] = array_merge($v1, [$key => $inputs[$key]]);
}
}
$combinations = $tmp;
}
echo "<pre>";
print_r($combinations);
?>
$output = array();
foreach($inputs['size'] as $size)
{
foreach($inputs['colour'] as $colour)
{
foreach($inputs['option'] as $option)
{
$output[] = array('size' => $size, 'colour' => $colour, 'option' => $option);
}
}
}
return $output;
Update :
$collection = collect($inputs[0]);
array_shift($inputs);
$matrix = $collection->crossJoin($inputs);
$matrix->all();
Update :
$collection = collect(array_shift($inputs));
$matrix = $collection->crossJoin($inputs);
$matrix->all();
Update :
use this function
function combinations($arrays, $i = 0) {
if (!isset($arrays[$i])) {
return array();
}
if ($i == count($arrays) - 1) {
return $arrays[$i];
}
// get combinations from subsequent arrays
$tmp = combinations($arrays, $i + 1);
$result = array();
// concat each array from tmp with each element from $arrays[$i]
foreach ($arrays[$i] as $v) {
foreach ($tmp as $t) {
$result[] = is_array($t) ?
array_merge(array($v), $t) :
array($v, $t);
}
}
return $result;
}
Related
I will try to explain everything :)
I have 2 arrays:
$packs = array(
array(
'name' => 'Pack 1',
'zones' => array(
array('zone' => 2),
array('zone' => 2),
)
),
array(
'name' => 'Pack 2',
'zones' => array(
array('zone' => 2),
array('zone' => 2),
array('zone' => 2),
)
),
array(
'name' => 'Pack 3',
'zones' => array(
array('zone' => 2),
array('zone' => 3),
)
),
array(
'name' => 'Pack 4',
'zones' => array(
array('zone' => 3),
array('zone' => 3),
)
)
);And products:
$products = array(
array(
'id' => '1',
'zone' => '2'
),
array(
'id' => '8',
'zone' => '2'
),
array(
'id' => '13',
'zone' => '3'
),
array(
'id' => '11',
'zone' => '2'
),
array(
'id' => '10',
'zone' => '2'
),
array(
'id' => '12',
'zone' => '3'
)
);
Then I would like to have all $packs zones combination with those products zones.
For example, products_zones are 2, 2, 3, 2, 2, 3 then I would like something like this:
Packs:
Combination 1:
Pack 1 (when Pack zones are in Products Zones, add pack to combination and remove products from array)
Pack 1
Combination 2:
Pack 1
Pack 3
Combination 3:
Pack 1
Pack 4
Combination 4:
Pack 2
Pack 4
Combination 5:
Pack 2
Pack 2
Pack 4
I'm trying to do that with recursive function but doesn't work. I leave here a link with code:
function search_recursive( $packs = array(), $products = array(), $packs_in = array(), $pass = null ) {
foreach ($packs as $index => $pack) {
// Get zones to compare
$arr_zones = array_column($pack['zonas'], 'zona');
$products_zones = array_column($products, 'zone');
// Check if pack zones are in product zones
$cheak_arr = [];
$arr_zones_temp = $arr_zones;
foreach ($products_zones as $index2 => $temp_zone) {
if ( in_array($temp_zone, $arr_zones_temp) ) {
$cheak_arr[] = $temp_zone;
foreach ($arr_zones_temp as $key => $value) {
if ( $value == $temp_zone ) {
unset($arr_zones_temp[$key]);
break;
}
}
}
}
if ( count($arr_zones) == count($cheak_arr) ) {
// I create a index for first time
$custom_index = ($pass == null) ? $index : $pass;
// Add pack to array if pack zones are in product zones
if ( !isset($packs_in[$custom_index]) ) {
$packs_in[$custom_index] = [
'packs' => array($pack)
];
}
else {
$packs_in[$custom_index]['packs'][] = $pack;
}
// Remove products that have zones same in pack
$temp_prod = $products;
foreach ($arr_zones as $zone) {
foreach ($temp_prod as $key => $value) {
if ( $value['zone'] == $zone ) {
unset($temp_prod[$key]);
break;
}
}
}
if ( $pass != null ) {
$products = $temp_prod;
}
if ( !empty($temp_prod) ) {
// Call myself with less products and index defined
$packs_in = search_recursive( $packs, $temp_prod, $packs_in, $custom_index );
}
else if ( $pass != null ) {
break;
}
}
}
return $packs_in;
}
I think I got what you need, but I'm still a bit confused. Anyway, I suggest you to simplify you "packs" array like my code below:
<?php
$packs = array(
array(
'name' => 'Pack 1',
'zones' => array(2,2),
),
array(
'name' => 'Pack 2',
'zones' => array(2,2,2),
),
array(
'name' => 'Pack 3',
'zones' => array(2,3),
),
array(
'name' => 'Pack 4',
'zones' => array(3,3),
)
);
$products = array(
array(
'id' => '8',
'zone' => '2'
),
array(
'id' => '13',
'zone' => '3'
),
array(
'id' => '11',
'zone' => '2'
),
array(
'id' => '10',
'zone' => '2'
),
array(
'id' => '12',
'zone' => '3'
)
);
$product_zones = array_column($products, 'zone');
//let's order an change to a sequence of numbers like 22233
sort($product_zones);
$product_zones = join('', $product_zones);
$combinations = [];
//here we iterate through all packs 1->2,3,4; 2->3,4 3->4 to find if it matches
foreach($packs as $k => $pack) {
// use k+1 if you can't match the pack with itself
for ($i = $k, $c = count ($packs); $i < $c; $i++) {
//here we do the same as before to combine the packs as string, ex.: 2223
$pack_zones = array_merge($pack['zones'], $packs[$i]['zones']);
sort($pack_zones);
$pack_zones = join('', $pack_zones);
//if it's a substring of our product zones then we have a valid combination
if (strpos($product_zones, $pack_zones) !== false) {
$combinations[] = [$pack['name'], $packs[$i]['name']];
}
}
}
print_r($combinations);
result: 1,3 (22223) ; 1,4 (2233) ; 2,4 (22233) ; 3,3 (2233)
How to sum array the same value of element ?
$arr = [
['id' => 1, 'qty' => 100, 'name' => 'a'],
['id' => 1, 'qty' => 100, 'name' => 'a'],
['id' => 2, 'qty' => 100, 'name' => 'b']
];
become to :
$arr = [
['id' => 1, 'qty' => 200, 'name' => 'a'],
['id' => 2, 'qty' => 100, 'name' => 'b']
];
i was try but return
[ 1=>['qty'=>200], 2=>['qty'=>100] ]
i was try but return
for($i=0; $i<count($cok);$i++){
$item_id = $cok[$i]['id'];
$quantity = $cok[$i]['quantity'];
if (isset($new_items[$item_id])) {
$new_items[$item_id] = ['quantity' => $new_items[$item_id]['quantity'] + $quantity];
} else {
$new_items[$item_id] = ['quantity' => $quantity];
}
}
Simple as pie (:
<?php
$arr = array(
array('id' => 1, 'qty' => 100, 'name' => 'a'),
array('id' => 1, 'qty' => 100, 'name' => 'a'),
array('id' => 2, 'qty' => 100, 'name' => 'b')
);
$new_arr = array();
foreach($arr AS $item) {
if(isset($new_arr[$item['id']])) {
$new_arr[$item['id']]['qty'] += $item['qty'];
continue;
}
$new_arr[$item['id']] = $item;
}
$arr = array_values($new_arr);
var_dump($arr);
Dive into my viper
And inplace snippet, returns exactly you need:
<?
$arr = array(
array('id' => 1, 'qty' => 100, 'name' => 'a'),
array('id' => 1, 'qty' => 100, 'name' => 'a'),
array('id' => 2, 'qty' => 100, 'name' => 'b')
);
$ids = array();
foreach ($arr as $i => $subarray) {
if (!($remove_from_array = array_key_exists($subarray['id'], $ids))) {
$ids[$subarray['id']] = 0;
}
$ids[$subarray['id']] += $subarray['qty'];
if ($remove_from_array) {
unset($arr[$i]);
}
}
foreach ($arr as &$subarray) {
$subarray['qty'] = $ids[$subarray['id']];
}
print_r($arr);
I have array:
$adm_menu_old = array (
array(
'id' => 1,
'name' => 'Test1',
),
array(
'id' => 3,
'name' => 'Test3',
'childrens' => array(
array(
'id' => 31,
'name' => 'Test31',
),
array(
'id' => 32,
'name' => 'Test32',
'childrens' => array(
array(
'id' => 321,
'name' => 'Test321',
),
),
)
),
array(
'id' => 4,
'name' => 'Test4',
),
);
Say i know id value.
I need get path with all parents of this id.
For example i need get path to this element: id=321
i need get array with key name values:
array('Test3','Test32','Test321')
how should look like recursive function?
Try this function:
function getNames($id, $arr) {
$result = array();
foreach($arr as $key => $val) {
if(is_array($val)) {
if($val["id"] == $id) {
$result[] = $val["name"];
} elseif(!empty($val["childrens"]) && is_array($val["childrens"])) {
$sub_res = getNames($id, $val["childrens"]);
if(count($sub_res) > 0) {
$result[] = $val["name"];
$result = array_merge($result, $sub_res);
}
}
}
}
return $result;
}
everyone!
I'm stuck trying write a recursive function. =(
This is my function, which, as I expected, will turn my plain array into multidimensional one.
function BuildTree($src, $index=0) {
foreach ($src as $index=>$curentItem) {
$nextItem = (is_array($src[$index+1]))?$src[$index+1]:false;
unset($src[$index]);
if ($nextItem['d']==$curentItem['d']) $brunchArray[] = $curentItem['n'];
if ($nextItem['d']>$curentItem['d']) $brunchArray['childrens'] = BuildTree($src, $index);
if (!$nextItem || $nextItem['d']<$curentItem['d']) return $brunchArray;
}
}
Input array is something like this:
$input = array (
array(
'n' => 'Articles',
'd' => 0
),
array(
'n' => 'Article 1',
'd' => 1
),
array(
'n' => 'Books',
'd' => 0
),
array(
'n' => 'Book 1',
'd' => 1
),
array(
'n' => 'Book 2',
'd' => 1
),
array(
'n' => 'Chapter 1',
'd' => 2
),
array(
'n' => 'Chapter 2',
'd' => 2
)
);
And I want it to be converted into this:
array (
array(
'n' => 'Articles',
'd' => 0,
'childrens' => array (
array(
'n' => 'Article 1',
'd' => 1
),
)
),
array(
'n' => 'Books',
'd' => 0,
'childrens' => array (
array(
'n' => 'Book 1',
'd' => 1
),
array(
'n' => 'Book 2',
'd' => 1
'childrens' => array (
array(
'n' => 'Chapter 1',
'd' => 2
),
array(
'n' => 'Chapter 2',
'd' => 2
)
)
)
)
)
)
I already spent three hours trying to solve this. =( Any help will be highly appreciated!
Here is a solution without recursion:
function convert($arr) {
$stack = array();
$output = array();
$arr[] = array('d' => -1); // Dummy record at the end
for($i = 0; $i < count($arr); $i++) {
while(!empty($stack) && $stack[count($stack) - 1]['d'] > $arr[$i]['d']) {
$current_d = $stack[count($stack) - 1]['d'];
$children = array();
while(!empty($stack) && $stack[count($stack) - 1]['d'] >= $current_d) {
$children[] = array_pop($stack);
}
$children = array_reverse($children);
if(empty($stack)) {
foreach($children as $child) {
$output[] = $child;
}
} else {
$stack[count($stack) - 1]['children'] = $children;
}
}
$stack[] = $arr[$i];
}
return $output;
}
$input = array (
array(
'n' => 'Articles',
'd' => 0
),
array(
'n' => 'Article 1',
'd' => 1
),
array(
'n' => 'Books',
'd' => 0
),
array(
'n' => 'Book 1',
'd' => 1
),
array(
'n' => 'Book 2',
'd' => 1
),
array(
'n' => 'Chapter 1',
'd' => 2
),
array(
'n' => 'Chapter 2',
'd' => 2
)
);
var_dump(convert($input));
Using the same $input:
$output = array();
function buildTree(&$input, &$output, &$current, $level = 0) {
if(!$input)
return;
$next = array_shift($input);
if($next['d'] == $level) {
$current[] = $next;
return buildTree($input, $output, $current, $level);
} else if($next['d'] == $level + 1) {
$current[count($current) - 1]['childrens'] = array($next);
return buildTree($input, $output, $current[count($current) - 1]['childrens'], $level + 1);
} else {
$output[] = $next;
return buildTree($input, $output, $output, 0);
}
}
buildTree($input, $output, $output);
var_dump($output);
There are simple 2d array with some sort of tree like this:
node1
node2
node3
It's structure is:
array(
array (
'id' : 1,
'pid': 0,
'title' : 'node1',
'level' : 1
),
array (
'id' : 2,
'pid': 1,
'title' : 'node2',
'level' : 2
),
array (
'id' : 3,
'pid': 2,
'title' : 'node3',
'level' : 3
),
)
Is there solutions with PHP to convert this array into:
array(
array (
'id' : 1,
'title' : 'node1',
'child' : array (
'id' : 2,
'title' : 'node2',
'child' : array (
'id' : 3,
'title' : 'node3',
),
),
)
...
)
Found #SO PHP Traversing Function to turn single array into nested array with children - based on parent id
$inArray = array(
array('ID' => '1', 'parentcat_ID' => '0'),
array('ID' => '2', 'parentcat_ID' => '0'),
array('ID' => '6', 'parentcat_ID' => '1'),
array('ID' => '7', 'parentcat_ID' => '1'),
array('ID' => '8', 'parentcat_ID' => '6'),
array('ID' => '9', 'parentcat_ID' => '1'),
array('ID' => '13', 'parentcat_ID' => '7'),
array('ID' => '14', 'parentcat_ID' => '8'),
);
function makeParentChildRelations(&$inArray, &$outArray, $currentParentId = 0) {
if(!is_array($inArray)) {
return;
}
if(!is_array($outArray)) {
return;
}
foreach($inArray as $key => $tuple) {
if($tuple['parentcat_ID'] == $currentParentId) {
$tuple['children'] = array();
makeParentChildRelations($inArray, $tuple['children'], $tuple['ID']);
$outArray[] = $tuple;
}
}
}
$outArray = array();
makeParentChildRelations($inArray, $outArray);
print_r($outArray);
<?php
$p = array(0 => array());
foreach($nodes as $n)
{
$pid = $n['pid'];
$id = $n['id'];
if (!isset($p[$pid]))
$p[$pid] = array('child' => array());
if (isset($p[$id]))
$child = &$p[$id]['child'];
else
$child = array();
$p[$id] = $n;
$p[$id]['child'] = &$child;
unset($p[$id]['pid']);
unset($p[$id]['level']);
unset($child);
$p[$pid]['child'][] = &$p[$id];
// $p[$pid]['child'] = &$p[$id]; // or this, if only one child
}
$nodes = $p['0']['child'];
unset($p);
?>
If each node can only have one child, then replace the one line with $p[$pid]['child'] = &$p[$id];.
(Edit: fixed it to work regardless of how the nodes are sorted.)