Related
I have the following array
Array ( [id] => 1 [name] => [cat_name] => Food & Beverage [quantity] => 1
[price] => 25 [image] => books_image/calories_fat_carbohydrate.png )
Array ( [id] => 2 [name] => [cat_name] => Food & Beverage [quantity] => 5
[price] => 38 [image] => books_image/the_law_relating_to_food.png )
Array ( [id] => 3 [name] => [cat_name] => Food & Beverage [quantity] => 5
[price] => 19 [image] => books_image/it_starts_with_food.png )
Array ( [id] => 3 [name] => [cat_name] => Food & Beverage [quantity] => 2
[price] => 19 [image] => books_image/it_starts_with_food.png )
In a $_SESSION['cartitem'] object, and the key is id.
My problem is that i have duplicates with id=3 and my desired output would be
Array ( [id] => 1 [name] => [cat_name] => Food & Beverage [quantity] => 1
[price] => 25 [image] => books_image/calories_fat_carbohydrate.png )
Array ( [id] => 2 [name] => [cat_name] => Food & Beverage [quantity] => 5
[price] => 38 [image] => books_image/the_law_relating_to_food.png )
Array ( [id] => 3 [name] => [cat_name] => Food & Beverage [quantity] => 7
[price] => 19 [image] => books_image/it_starts_with_food.png )
Basically merging by same id and adding the quantity field. Is there an easy way to do this in php?
I dont want to remove duplicates. The duplicates to me are important since they have quantities in which i need to add them.
Here you go:
// DEFINE SORTING CRITERIA
function sort_ids($a, $b) {
return $a['id'] > $b['id'];
}
// DEFINE ARRAY OF ARRAYS
$arrays = array(
array( 'id' => 1, 'name' => '', 'cat_name' => 'Food & Beverage', 'quantity' => 1,
'price' => 25, 'image' => 'books_image/calories_fat_carbohydrate.png' ),
array( 'id' => 2, 'name' => '', 'cat_name' => 'Food & Beverage', 'quantity' => 5,
'price' => 38, 'image' => 'books_image/the_law_relating_to_food.png' ),
array( 'id' => 3, 'name' => '', 'cat_name' => 'Food & Beverage', 'quantity' => 5,
'price' => 19, 'image' => 'books_image/it_starts_with_food.png' ),
array( 'id' => 3, 'name' => '', 'cat_name' => 'Food & Beverage', 'quantity' => 2,
'price' => 19, 'image' => 'books_image/it_starts_with_food.png' ),
array( 'id' => 1, 'name' => '', 'cat_name' => 'Food & Beverage', 'quantity' => 1,
'price' => 25, 'image' => 'books_image/calories_fat_carbohydrate.png' ),
array( 'id' => 2, 'name' => '', 'cat_name' => 'Food & Beverage', 'quantity' => 5,
'price' => 38, 'image' => 'books_image/the_law_relating_to_food.png' )
);
// SORT ARRAY OF ARRAYS FIRST
usort($arrays, 'sort_ids');
// MERGE DUPLICATES
$record_number = count($arrays);
for ($i=0; $i<$record_number; $i++) {
// if this is not the first loop and if this is a duplicate
if(isset($temp_id) && $temp_id == $arrays[$i]['id']) {
// add quantity of the previous array here
$arrays[$i]['quantity'] += $temp_quantity;
// unset previous array
unset($arrays[$i-1]);
}
$temp_id = $arrays[$i]['id'];
$temp_quantity = $arrays[$i]['quantity'];
}
// PRINT ARRAY OF ARRAYS
echo '<pre>';
print_r($arrays);
echo '</pre>';
I have a below PHP array in which you can see category/sub-category structure based on "parent_id" & "parent" element.
Now the requirement is, on the basis of "menu_display_special = 1" condition, I want to delete that key as well as the keys which have this key's id as parent_id.
Note: If the "menu_display_special = 1" condition matches, it should remove the keys from category & sub-categories(if any) from the array.
Result should return only one array element. i.e. id = 2378
Array
(
[35] => Joomla\CMS\Menu\MenuItem Object
(
[id] => 2375
[params:protected] => Joomla\Registry\Registry Object
(
[data:protected] => stdClass Object
(
[menu_display_special] => 1
)
)
[parent_id] => 2376
[parent] =>
)
[36] => Joomla\CMS\Menu\MenuItem Object
(
[id] => 2377
[params:protected] => Joomla\Registry\Registry Object
(
[data:protected] => stdClass Object
(
)
)
[parent_id] => 2376
[parent] => 1
)
[37] => Joomla\CMS\Menu\MenuItem Object
(
[id] => 2379
[params:protected] => Joomla\Registry\Registry Object
(
[data:protected] => stdClass Object
(
[menu_display_special] => 1
)
)
[parent_id] => 2377
[parent] =>
)
[38] => Joomla\CMS\Menu\MenuItem Object
(
[id] => 2380
[params:protected] => Joomla\Registry\Registry Object
(
[data:protected] => stdClass Object
(
[menu_display_special] => 1
)
)
[parent_id] => 2377
[parent] =>
)
[39] => Joomla\CMS\Menu\MenuItem Object
(
[id] => 2381
[params:protected] => Joomla\Registry\Registry Object
(
[data:protected] => stdClass Object
(
[menu_display_special] => 1
)
)
[parent_id] => 2377
[parent] =>
)
[40] => Joomla\CMS\Menu\MenuItem Object
(
[id] => 2378
[params:protected] => Joomla\Registry\Registry Object
(
[data:protected] => stdClass Object
(
)
)
[parent_id] => 2376
[parent] =>
)
)
Code After var_export :
array (
35 =>
Joomla\CMS\Menu\MenuItem::__set_state(array(
'id' => '2375',
'params' =>
Joomla\Registry\Registry::__set_state(array(
'data' =>
stdClass::__set_state(array(
'menu_display_special' => '1',
)),
)),
'parent_id' => '2376',
'parent' => false,
)),
36 =>
Joomla\CMS\Menu\MenuItem::__set_state(array(
'id' => '2377',
'params' =>
Joomla\Registry\Registry::__set_state(array(
'data' =>
stdClass::__set_state(array(
'menu_display_special' => '1',
)),
)),
'parent_id' => '2376',
'parent' => true,
)),
37 =>
Joomla\CMS\Menu\MenuItem::__set_state(array(
'id' => '2379',
'params' =>
Joomla\Registry\Registry::__set_state(array(
'data' =>
stdClass::__set_state(array(
'menu_display_special' => '1',
)),
)),
'parent_id' => '2377',
'parent' => false,
)),
38 =>
Joomla\CMS\Menu\MenuItem::__set_state(array(
'id' => '2380',
'params' =>
Joomla\Registry\Registry::__set_state(array(
'data' =>
stdClass::__set_state(array(
'menu_display_special' => '1',
)),
)),
'parent_id' => '2377',
'parent' => false,
)),
39 =>
Joomla\CMS\Menu\MenuItem::__set_state(array(
'id' => '2381',
'params' =>
Joomla\Registry\Registry::__set_state(array(
'data' =>
stdClass::__set_state(array(
)),
)),
'parent_id' => '2377',
'parent' => false,
)),
40 =>
Joomla\CMS\Menu\MenuItem::__set_state(array(
'id' => '2378',
'params' =>
Joomla\Registry\Registry::__set_state(array(
'data' =>
stdClass::__set_state(array(
)),
)),
'parent_id' => '2376',
'parent' => false,
)),
)
Coding attempt : but it returns 2 array element i.e. 2381 & 2378. It should give me only 2378 as 2381 is child of 2377( which has menu_display_special value 1)
$listArray = array_filter($list,
function($v) use($list) {
return $v->params->get('menu_display_special') != '1' && ($v->parent == TRUE || $list[$v->parent_id]['params']['menu_display_special'] != '1');
}
);
I'm not sure if your design requirements allow me to merge the conditions in my recursive function, so I've kept them separate to try to be ultimately accurate.
There is no return value and $array is preceded by a & to make it modify the originally passed input array.
Code (Demo)
function recurse(&$array, $pid = null) {
foreach ($array as $id => $item) {
if (isset($item->params->data->menu_display_special) && $item->params->data->menu_display_special == 1) {
unset($array[$id]);
recurse($array, $item->id);
} elseif ($item->parent_id === $pid) {
unset($array[$id]);
}
}
}
$list = [
35 => (object)[
'id' => '2375',
'params' => (object)[
'data' => (object)[
'menu_display_special' => '1'
]
],
'parent_id' => '2376',
'parent' => false
],
36 => (object)[
'id' => '2377',
'params' => (object)[
'data' => (object)[
'menu_display_special' => '1'
]
],
'parent_id' => '2376',
'parent' => false
],
37 => (object)[
'id' => '2379',
'params' => (object)[
'data' => (object)[
'menu_display_special' => '1'
]
],
'parent_id' => '2377',
'parent' => false
],
38 => (object)[
'id' => '2380',
'params' => (object)[
'data' => (object)[
'menu_display_special' => '1'
]
],
'parent_id' => '2377',
'parent' => false
],
39 => (object)[
'id' => '2381',
'params' => (object)[
'data' => (object)[]
],
'parent_id' => '2377',
'parent' => false
],
40 => (object)[
'id' => '2378',
'params' => (object)[
'data' => (object)[]
],
'parent_id' => '2376',
'parent' => false
],
];
recurse($list);
var_export($list);
Output:
array (
40 =>
(object) array(
'id' => '2378',
'params' =>
(object) array(
'data' =>
(object) array(
),
),
'parent_id' => '2376',
'parent' => false,
),
)
I have an array of StdClass Objects and want to return the "partner_code" with the minimum value for key "price". So for this example I would like to return partner_code "AC" as it is the partner with the lowest price. I tried using array_reduce, but I'm not sure what I'm doing wrong. Any help would be appreciated. Please note I am not looking to SORT this array. I just want to move the subarray containing AC (because it hold the lowest price) to the top - not sorting everything by price
Input Array:
Array
(
[0] => stdClass Object
(
[name] => Budget
[partner_code] => BU
[price] => 365.36
[tier] => 1
)
[1] => stdClass Object
(
[name] => Avis
[partner_code] => AV
[price] => 449.71
[tier] => 1
)
[2] => stdClass Object
(
[name] => E-Z
[partner_code] => EZ
[price] => 270.56
[tier] => 2
)
[3] => stdClass Object
(
[name] => Sixt
[partner_code] => SX
[price] => 280.52
[tier] => 2
)
[4] => stdClass Object
(
[name] => Alamo
[partner_code] => AL
[price] => 345.13
[tier] => 2
)
[5] => stdClass Object
(
[name] => Advantage
[partner_code] => AD
[price] => 357.61
[tier] => 2
)
[6] => stdClass Object
(
[name] => Enterprise
[partner_code] => ET
[price] => 364.46
[tier] => 2
)
[7] => stdClass Object
(
[name] => ACE
[partner_code] => AC
[price] => 186.53
[tier] => 3
)
[8] => stdClass Object
(
[name] => Fox
[partner_code] => FX
[price] => 265.25
[tier] => 3
)
[9] => stdClass Object
(
[name] => Payless
[partner_code] => ZA
[price] => 380.47
[tier] => 3
)
[10] => stdClass Object
(
[name] => Dollar
[partner_code] => ZR
[price] => 385.99
[tier] => 3
)
[11] => stdClass Object
(
[name] => Thrifty
[partner_code] => ZT
[price] => 385.99
[tier] => 3
)
[12] => stdClass Object
(
[name] => Silvercar
[partner_code] => SC
[price] => 424.10
[tier] => 3
)
[13] => stdClass Object
(
[name] => National
[partner_code] => NA
[price] => 448.82
[tier] => 3
)
[14] => stdClass Object
(
[name] => Hertz
[partner_code] => HZ
[price] => 487.33
[tier] => 3
)
)
Code:
array_reduce($this->results->companies, function($a,$b) {
echo "Prices: " . $a->price . "<br>";
return $a->price < $b->price ? (string)$a->partner_code : (string)$b->partner_code;
});
usort($array, function($a, $b) {
return ($a->price - $b->price) ;
});
echo $array[0]->partner_code;
If you really don't want to sort the array but instead use array_reduce, do so by reducing the array to one of its elements. Then you can get the partner_code property for that element.
For example
array_reduce($this->results->companies, function($lowest, $company) {
// $lowest will be null on the first iteration
return $lowest === null || $company->price < $lowest->price ?
$company : $lowest;
})->partner_code;
This method will not sort the entire array. It will pull out the subarray with the lowest price and set it as the first element. I could have nested some of the functions to make it more compact (1-liner), but that would have damaged readability.
Code: (Demo)
$results=[
(object)["name"=>"Budget","partner_code"=>"BU","price"=>"365.36","tier"=>"1"],
(object)["name"=>"Avis","partner_code"=>"AV","price"=>"449.71","tier"=>"1"],
(object)["name"=>"E-Z","partner_code"=>"EZ","price"=>"270.56","tier"=>"2"],
(object)["name"=>"Sixt","partner_code"=>"SX","price"=>"280.52","tier"=>"2"],
(object)["name"=>"Alamo","partner_code"=>"AL","price"=>"345.13","tier"=>"2"],
(object)["name"=>"Advantage","partner_code"=>"AD","price"=>"357.61","tier"=>"2"],
(object)["name"=>"Enterprise","partner_code"=>"ET","price"=>"364.46","tier"=>"2"],
(object)["name"=>"ACE","partner_code"=>"AC","price"=>"186.53","tier"=>"3"],
(object)["name"=>"Fox","partner_code"=>"FX","price"=>"265.25","tier"=>"3"],
(object)["name"=>"Payless","partner_code"=>"ZA","price"=>"380.47","tier"=>"3"],
(object)["name"=>"Dollar","partner_code"=>"ZR","price"=>"385.99","tier"=>"3"],
(object)["name"=>"Thrifty","partner_code"=>"ZT","price"=>"385.99","tier"=>"3"],
(object)["name"=>"Silvercar","partner_code"=>"SC","price"=>"424.10","tier"=>"3"],
(object)["name"=>"National","partner_code"=>"NA","price"=>"448.82","tier"=>"3"],
(object)["name"=>"Hertz","partner_code"=>"HZ","price"=>"487.33","tier"=>"3"]
];
$min=min(array_column($results,'price')); // find the minimum value
$index=array_search($min,array_column($results,'price')); // find the index of the subarray containing min value
$pulled=array_splice($results,$index,1); // extract the subarray and preserve it as $pulled
$new_results=array_merge($pulled,$results); // set $pulled as first element
var_export($new_results);
...okay, okay, here's the one-liner:
var_export(array_merge(array_splice($results,array_search(min(array_column($results,'price')),array_column($results,'price')),1),$results));
Output:
array (
0 =>
stdClass::__set_state(array(
'name' => 'ACE',
'partner_code' => 'AC',
'price' => '186.53',
'tier' => '3',
)),
1 =>
stdClass::__set_state(array(
'name' => 'Budget',
'partner_code' => 'BU',
'price' => '365.36',
'tier' => '1',
)),
2 =>
stdClass::__set_state(array(
'name' => 'Avis',
'partner_code' => 'AV',
'price' => '449.71',
'tier' => '1',
)),
3 =>
stdClass::__set_state(array(
'name' => 'E-Z',
'partner_code' => 'EZ',
'price' => '270.56',
'tier' => '2',
)),
4 =>
stdClass::__set_state(array(
'name' => 'Sixt',
'partner_code' => 'SX',
'price' => '280.52',
'tier' => '2',
)),
5 =>
stdClass::__set_state(array(
'name' => 'Alamo',
'partner_code' => 'AL',
'price' => '345.13',
'tier' => '2',
)),
6 =>
stdClass::__set_state(array(
'name' => 'Advantage',
'partner_code' => 'AD',
'price' => '357.61',
'tier' => '2',
)),
7 =>
stdClass::__set_state(array(
'name' => 'Enterprise',
'partner_code' => 'ET',
'price' => '364.46',
'tier' => '2',
)),
8 =>
stdClass::__set_state(array(
'name' => 'Fox',
'partner_code' => 'FX',
'price' => '265.25',
'tier' => '3',
)),
9 =>
stdClass::__set_state(array(
'name' => 'Payless',
'partner_code' => 'ZA',
'price' => '380.47',
'tier' => '3',
)),
10 =>
stdClass::__set_state(array(
'name' => 'Dollar',
'partner_code' => 'ZR',
'price' => '385.99',
'tier' => '3',
)),
11 =>
stdClass::__set_state(array(
'name' => 'Thrifty',
'partner_code' => 'ZT',
'price' => '385.99',
'tier' => '3',
)),
12 =>
stdClass::__set_state(array(
'name' => 'Silvercar',
'partner_code' => 'SC',
'price' => '424.10',
'tier' => '3',
)),
13 =>
stdClass::__set_state(array(
'name' => 'National',
'partner_code' => 'NA',
'price' => '448.82',
'tier' => '3',
)),
14 =>
stdClass::__set_state(array(
'name' => 'Hertz',
'partner_code' => 'HZ',
'price' => '487.33',
'tier' => '3',
)),
)
I think this is a leaner method generating the same/desired result: (Demo)
$min=$results[0]->price; // set initial/default min value
$index=0; // set initial/default index
foreach($results as $i=>$a){
if($a->price<$min){ // if a lower price...
$min=$a->price; // store new $min
$index=$i; // stor new $index
}
}
$results=array_merge($results,array_splice($results,$index,1)); // extract lowest and move to front of array
var_export($results);
Here is input array with an n-level depth
array
(
[0] => array
(
[id] => 1
[parent_id] => 0
[variable_name] => menus
[variable_value] =>
[children] => array
(
[0] => array
(
[id] => 2
[parent_id] => 1
[variable_name] => products
[variable_value] => {"name":"Products", "link":"cctv.html", "show":"1"},
)
[1] => array
(
[id] => 3
[parent_id] => 1
[variable_name] => companies
[variable_value] => {"name":"Companies", "link":"companies.html", "show":"1"},
),
),
)
[1] => array
(
[id] => 4
[parent_id] => 0
[variable_name] => breadcrumbs
[variable_value] =>
[children] => array
(
[0] => array
(
[id] => 5
[parent_id] => 4,
)
[1] => array
(
[id] => 6
[parent_id] => 4
[variable_name] => companies
[variable_value] => {"name":"Companies", "link":"companies.html", "show":"1"},
),
),
)
[2] => array
(
[id] => 7
[parent_id] => 0
[variable_name] => products
[variable_value] =>
[children] => array
(
[0] => array
(
[id] => 8
[parent_id] => 7
[variable_name] => pages
[variable_value] =>
[children] => array
(
[0] => array
(
[id] => 9
[parent_id] => 8
[variable_name] => child_category_page
[variable_value] =>
[children] => array
(
[0] => array
(
[id] => 10
[parent_id] => 9
[variable_name] => middle
[variable_value] =>
[children] => array
(
[0] => array
(
[id] => 11
[parent_id] => 10
[variable_name] => left
[variable_value] => {"name":"Companies", "link":"companies.html", "show":"1", "test":1},
),
),
),
),
),
),
),
),
),
)
I want to convert it into,
[
'menus' => [
'products' => [
'name' => 'Products',
'link' => 'cctv.html',
'show' => true,
],
'companies' => [
'name' => 'Companies',
'link' => 'companies.html',
'show' => true,
],
],
'breadcrumbs' => [
'news' => [
'text' => 'News',
'show' => true,
'link' => 'news.html',
],
'companies' => [
'text' => 'Companies',
'show' => true,
'link' => 'companies.html',
],
],
'products' => [
'pages' => [
'child_category_page' => [
'middle' => [
'left' => [
'text' => 'Companies',
'show' => true,
'link' => 'companies.html',
],
],
],
],
],
];
What I have tried is,
$data = DB::table("SITE_CONFIGS")->where("parent_id", 0)->get();
$data = get_tree_site_configs($data);
function get_tree_site_configs($data, $parent=0, &$result=[]){
$data = json_decode(json_encode($data),true);
$branch = [];
foreach ($data as $key => &$value) {
if($parent == $value['parent_id']){
$has_sub = DB::table("SITE_CONFIGS")->where("parent_id", $value['id'])->get();
$children = get_tree_site_configs($has_sub, $value['id'],$result);
if($children){
$value['children'] = $children;
}
// pr($value);
$branch[] = $value;
}
}
return $branch;
}
Note: There is parent-child relation to n-level, parent id with variable_value are leaf notes, means they don't have any children, rest all are parents of some records.
function get_tree_site_configs(array $config) {
$result = [];
foreach ($config as $item) {
if (isset($item['children'])) {
$value = get_tree_site_configs($item['children']);
} else {
$value = $item['variable_value'];
}
$result[$item['variable_name']] = $value;
}
return $result;
}
I have been trying to get this to work for 7.5 hours now, but my brain has melted.
I have a multi-dimensional array similar to the following:
array (
'expanded' => true,
'key' => 'root_1',
'title' => 'root',
'children' =>
array (
0 =>
array (
'folder' => false,
'key' => '_1',
'title' => 'News',
'data' =>
array (
'id' => '3',
'parent_id' => 0,
),
),
1 =>
array (
'folder' => true,
'key' => '_2',
'title' => 'Animations',
'data' =>
array (
'id' => '5',
'parent_id' => '0',
),
'children' =>
array (
0 =>
array (
'folder' => false,
'key' => '_3',
'title' => 'The Simpsons',
'data' =>
array (
'id' => '1',
'parent_id' => '5',
),
),
1 =>
array (
'folder' => false,
'key' => '_4',
'title' => 'Futurama',
'data' =>
array (
'id' => '4',
'parent_id' => '5',
),
),
),
),
2 =>
array (
'folder' => true,
'key' => '_5',
'title' => 'Episodes',
'data' =>
array (
'id' => '6',
'parent_id' => '0',
),
'children' =>
array (
0 =>
array (
'folder' => true,
'key' => '_6',
'title' => 'UK Episodes',
'data' =>
array (
'id' => '7',
'parent_id' => '6',
),
'children' =>
array (
0 =>
array (
'folder' => false,
'key' => '_7',
'title' => 'Coupling',
'data' =>
array (
'id' => '2',
'parent_id' => '7',
),
),
),
),
1 =>
array (
'folder' => true,
'key' => '_8',
'title' => 'AU Episodes',
'data' =>
array (
'id' => '8',
'parent_id' => '6',
),
),
),
),
),
)
I need to search through all sub arrays and build a new array returning the id and parent_id of each of the children AND also interpreting the order of the array children from the order they appear in the original array.
The output needs to end up something like this:
Array
(
[0] => Array
(
[id] => 1
[parent_id] => 5
[order] => 1
)
[1] => Array
(
[id] => 2
[parent_id] => 7
[order] => 1
)
[2] => Array
(
[id] => 4
[parent_id] => 5
[order] => 2
)
)
I have tried the following recursion approach, however my code turns into a mess, and thats before I've even attempted to set the order of the items.
I've also searched stackoverflow for another example that I could learn from however I haven't found anything yet... If there is another example please feel free to point me in the right direction.
I appreciate any assistance!
A super easy way to run over all these is to use a RecursiveIteratorIterator over a RecursiveArrayIterator, pluck out the 'data' arrays and add in the key as the order.
Example:
$array = []; // Your starting array with stuff in it.
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST
);
$result = [];
foreach ($iterator as $key => $value) {
if (isset($value['data'])) {
$result[] = array_merge($value['data'], ['order' => $key]);
}
}
print_r($result);
Output:
Array
(
[0] => Array
(
[id] => 3
[parent_id] => 0
[order] => 0
)
[1] => Array
(
[id] => 5
[parent_id] => 0
[order] => 1
)
[2] => Array
(
[id] => 1
[parent_id] => 5
[order] => 0
)
[3] => Array
(
[id] => 4
[parent_id] => 5
[order] => 1
)
[4] => Array
(
[id] => 6
[parent_id] => 0
[order] => 2
)
[5] => Array
(
[id] => 7
[parent_id] => 6
[order] => 0
)
[6] => Array
(
[id] => 2
[parent_id] => 7
[order] => 0
)
[7] => Array
(
[id] => 8
[parent_id] => 6
[order] => 1
)
)
If i'm understanding what you're trying to do properly the below snippet should work. No need for the order key in each sub array because that's recorded automatically when you insert a new array index into $new_array.
Let me know if you have any other problems.
$new_array = [];
$current_array = []; //with all your data
foreach($current_array['children'] as $array) {
$new_array[] = [
'id' => $array['data']['id'],
'parent_id' => $array['data']['parent_id'];
];
}