I have a multidimensional array and I need to count how many items are in each category:
array (
array(
'name' => 'Bob',
'category' => '2'
),
array(
'name' => 'Bill',
'category' => '6'
),
array(
'name' => 'John',
'category' => '1'
),
array(
'name' => 'Jack',
'category' => '2'
),
)
I want to be able to split these up into categories.
For example;
Category 2 contains 2 items
Category 1 contains 1 item
Category 6 contains 1 item
Just to get the count of each category would be great, but to be able to re-arrange the array into categories would also be useful. I'd like to be able to do both.
I've tried searching StackOverflow but I couldn't find this specific query. I'm guessing this may use array_map somewhere but I'm not good with that function.
Any help is greatly appreciated!
If your array isn't too big a straightforward approach might be the easiest one. Create a new array, use categories as keys and iterate over your array, counting items.
I have written 3 functions that solves the criteria you have described. Keep in mind these functions are bare minimum and lack error handling. It is also assumed the $categories array which all the functions requires has the structure outlined in your question.
The first rearranges all items into the correct category.
function rearrangeCategories(array $categories) {
$calculated = [];
foreach($categories as $category) {
$calculated[$category['category']][] = $category['name'];
}
return $calculated;
}
The second creates an associative array of the amount of items in each category. The array index is the category name/id and the value is an integer declaring the amount of items.
function categoriesCount(array $categories) {
$calculated = [];
$arranged = rearrangeCategories($categories);
foreach($arranged as $category => $values) {
$calculated[$category] = count($values);
}
return $calculated;
}
The third function checks how many items are stored inside a specific category. If the category doesn't exists FALSE is returned. Otherwise an integer is returned.
function categoriesItemCount(array $categories, $key) {
$arranged = rearrangeCategories($categories);
if(!array_key_exists($key, $arranged)) {
return false;
}
return count($arranged[$key]);
}
I hope this helps, happy coding.
You can use something like this
$arr =
array (
array(
'name' => 'Bob',
'category' => '2'
),
array(
'name' => 'Bill',
'category' => '6'
),
array(
'name' => 'John',
'category' => '1'
),
array(
'name' => 'Jack',
'category' => '2'
),
);
$categoryCount = array();
$categoryList = array();
array_map(function($a) use (&$categoryCount, &$categoryList) {
$categoryId = $a['category'];
if (!isset($categoryCount[$categoryId])) {
$categoryCount[$categoryId] = 0;
}
$categoryCount[$categoryId]++;
if (!isset($categoryList[$categoryId])) {
$categoryList[$categoryId] = array();
}
$categoryList[$categoryId][] = $a['name'];
}, $arr);
print_r($categoryCount);
print_r($categoryList);
This will create 2 arrays: one with the counts and one with the elements rearranged
Try this way, i think it will fulfill your requirements.
$arr=array (
array(
'name' => 'Bob',
'category' => '2'
),
array(
'name' => 'Bill',
'category' => '6'
),
array(
'name' => 'John',
'category' => '1'
),
array(
'name' => 'Jack',
'category' => '2'
),
);
$result = call_user_func_array('array_merge_recursive', $arr);
//for just show array
print '<pre>';
print_r(array_count_values($result['category']));
print '</pre>';
//loop as you need
foreach(array_count_values($result['category']) as $k=>$v){
$item=($v>1)? 'items':'item';
echo "Category ".$k." Contains " .$v." ".$item."<br/>";
}
Related
I have an array of arrays, as such
$statuses = array(
[0] => array('id'=>10, 'status' => 'active'),
[1] => array('id'=>11, 'status' => 'closed'),
[2] => array('id'=>12, 'status' => 'active'),
[3] => array('id'=>13, 'status' => 'stopped'),
)
I want to be able to make a new array of arrays and each of those sub arrays would contain the elements based on if they had the same status.
The trick here is, I do not want to do a case check based on hard coded status names as they can be random. I want to basically do a dynamic comparison, and say "if you are unique, then create a new array and stick yourself in there, if an array already exists with the same status than stick me in there instead". A sample result could look something like this.
Ive really had a challenge with this because the only way I can think to do it is check every single element against every other single element, and if unique than create a new array. This gets out of control fast if the original array is larger than 100. There must be some built in functions that can make this efficient.
<?php
$sortedArray = array(
['active'] => array(
array(
'id' => 10,
'status' => 'active'
),
array(
'id' => 12,
'status' => 'active'
)
),
['closed'] => array(
array(
'id' => 11,
'status' => 'active'
)
),
['stopped'] => array(
array(
'id' => 13,
'status' => 'active'
)
),
)
$SortedArray = array();
$SortedArray['active'] = array();
$SortedArray['closed'] = array();
$SortedArray['stopped'] = array();
foreach($statuses as $Curr) {
if ($Curr['status'] == 'active') { $SortedArray['active'][] = $Curr; }
if ($Curr['status'] == 'closed') { $SortedArray['closed'][] = $Curr; }
if ($Curr['status'] == 'stopped') { $SortedArray['stopped'][] = $Curr; }
}
You can also do it with functional way though it's pretty the same like Marc said.
$sorted = array_reduce($statuses, function($carry, $status) {
$carry[$status['status']][] = $status;
return $carry;
}, []);
I've got a multidimensional PHP array in that form:
array(
(int) 0 => array(
'Category' => array(
'id' => '01',
'title' => 'SomeCategory'
)
),
(int) 1 => array(
'Category' => array(
'id' => '02',
'title' => 'OtherCategory'
)
)
)
I want to get the title of the category with a specific id, e.g. SomeCategory when I have the id 01.
Is there a better (more performant or easier) way to do it than this one?
foreach($categories as $nestedCategory) {
foreach($nestedCategory as $category) {
if($category['id'] === $postedData['Submission.Category.0.id']) {
debug($category['title']);
}
}
}
Thanks!
If the id's are unique you could rewrite the array
foreach( $array as $n => $item ) {
$arr[$item['Category']['id']] = $item;
}
// get id 02
echo $arr['02']['Category']['title']; // output: OtherCategory
Hi I am new in PHP and I am trying to merge 2 arrays but I don't want to get duplicates.I have been stuck a week now.
I have first array:
$existed_product = array(array('name'=>"pano", 'code'=>"BR0001", 'qty'=>"2", 'price'=>"12"),
array('name'=>"ying", 'code'=>"AB001", 'qty'=>"5", 'price'=>"8"));
And I want to merge the second array:
$new_product= array('name'=>"pano", 'code'=>"BR0001", 'qty'=>"10", 'price'=>"12");
I want to merge them and when it found duplicate product, just replace it with a newer array(has qty=10). The result looks like this:
$final_array=array(array('name'=>"pano", 'code'=>"BR0001", 'qty'=>"10", 'price'=>"12"),
array('name'=>"ying", 'code'=>"AB001", 'qty'=>"5", 'price'=>"8"));
Please help me.Thank you
Assuming new product always is a single array, and code is the identifyer, something like this
$existed_product = array(
array(
'name' => 'pano',
'code' => 'BR0001',
'qty' => '2',
'price' => '12' ),
array(
'name' => 'ying',
'code' => 'AB001',
'qty' => '5',
'price' => '8'
)
);
echo '<pre>', print_r( $existed_product, true ), '</pre>';
$new_product = array(
'name' => 'pano',
'code' => 'BR0001',
'qty' => '10',
'price' => '12'
);
foreach ( $existed_product as $no => $product ) {
if ( $new_product['code'] == $product['code'] ) {
$existed_product[$no]['qty'] = $new_product['qty'];
$existed_product[$no]['price'] = $new_product['price'];
}
}
echo '<pre>', print_r( $existed_product, true ), '</pre>';
Well, I am here again dealing with arrays in php. I need your hand to guide me in the right direction. Suppose the following array:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
The - (hyphen) symbol only illustrates the deep level.
Well, I need to build another array (or whatever), because it should be printed as an HTML select as below:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
Looks that for each level element, it should add a space, or hyphen to determinate that it belongs to a particular parent.
EDIT
The have provide an answer provideng my final code. The html select element will display each level as string (repeating the "-" at the begging of the text instead multi-level elements.
Here's a simple recursive function to build a select dropdown given an array. Unfortunately I'm not able to test it, but let me know if it works. Usage would be as follows:
function generateDropdown($array, $level = 1)
{
if ($level == 1)
{
$menu = '<select>';
}
foreach ($array as $a)
{
if (is_array($a))
{
$menu .= generateDropdown($a, $level+1);
}
else
{
$menu .= '<option>'.str_pad('',$level,'-').$a.'</option>'."\n";
}
}
if ($level == 1)
{
$menu = '</select>';
}
return $menu;
}
OK, I got it with the help of #jmgardhn2.
The data
This is my array:
$temp = array(
array(
'name' => 'fruits',
'sons' => array(
array(
'name' => 'green',
'sons' => array(
array(
'name' => 'mango'
),
array(
'name' => 'banana',
)
)
)
)
),
array(
'name' => 'cars',
'sons' => array(
array(
'name' => 'italy',
'sons' => array(
array(
'name' => 'ferrari',
'sons' => array(
array(
'name' => 'red'
),
array(
'name' => 'black'
),
)
),
array(
'name' => 'fiat',
)
)
),
array(
'name' => 'germany',
'sons' => array(
array(
'name' => 'bmw',
)
)
),
)
)
);
Recursive function
Now, the following function will provide an array with items like [level] => [name]:
function createSelect($tree, $items, $level)
{
foreach ($tree as $key)
{
if (is_array($key))
{
$items = createSelect($key, $items, $level + 1);
}
else
{
$items[] = array('level' => $level, 'text' => $key);
}
}
return $items;
}
Calling the funcion
Now, call the function as below:
$items = createSelect($temp, array(), 0);
Output
If you iterate the final $items array it will look like:
1fruits
2green
3mango
3banana
1cars
2italy
3ferrari
4red
4black
3fiat
2germany
3bmw
I have a multi-dimensional array that looks like this:
The base array is indexed based on category ids from my catalog.
$cat[category_id]
Each base array has three underlying elements:
['parent_id']
['sort_order']
['name']
I want to create a function that allows us to create a list of category_id's and names for a given parent_category_id in the correct sort order. Is this possible? Technically it is the same information, but the array is constructed in a weird way to extract that information.
Here is an example definition for the array:
$cat = array();
$cat[32]['parent_id']= 0;
$cat[32]['sort_order']= 1;
$cat[32]['name']= 'my-category-name1';
$cat[45]['parent_id']= 0;
$cat[45]['sort_order']= 0;
$cat[45]['name']= 'my-category-name2';
$cat[2]['parent_id']= 0;
$cat[2]['sort_order']= 2;
$cat[2]['name'] = "my-category-name3";
$cat[3]['parent_id']= 2;
$cat[3]['sort_order']= 1;
$cat[3]['name'] = "my-category-name4";
$cat[6]['parent_id']= 2;
$cat[6]['sort_order']= 0;
$cat[6]['name'] = "my-category-name5";
Assuming it's something of this sort:
$ary = Array(
0 => Array(
'parent_category_id' => null,
'sort_order' => 0,
'name' => 'my-category-name0'
),
1 => Array(
'parent_category_id' => 0,
'sort_order' => 1,
'name' => 'my-category-name1'
),
2 => Array(
'parent_category_id' => 0,
'sort_order' => 2,
'name' => 'my-category-name2'
),
3 => Array(
'parent_category_id' => null,
'sort_order' => 0,
'name' => 'my-category-name3'
),
4 => Array(
'parent_category_id' => 3,
'sort_order' => 0,
'name' => 'my-category-name4'
)
);
You can use a combination of a foreach and usort to achieve what you're going for.
// #array: the array you're searchign through
// #parent_id: the parent id you're filtering by
function getFromParent($array, $parent_id){
$result = Array();
foreach ($array as $category_id => $entry){
if ($entry['parent_category_id']===$parent_id)
$result[$category_id] = $entry;
}
usort($result,create_function('$a,$b','return ($a["sort_order"]>$b["sort_order"]?1:($b["sort_order"]<$a["sort_order"]?-1:0));'));
return $result;
}
var_export(getFromParent($ary,0));
EDIT Sorry, fixed some syntax errors. Tested, and works (at least to result in what I was intending)
EDITv2 Here's the raw output from the above:
array (
0 =>
array (
'parent_category_id' => 0,
'sort_order' => 1,
'name' => 'my-category-name1',
),
1 =>
array (
'parent_category_id' => 0,
'sort_order' => 2,
'name' => 'my-category-name2',
),
)
(Used var_export just for you #FelixKling)
EDITv3 I've updated my answer to go along with the OP's update. I also now make it retain the original "category_id" values in the result array.
First you create an empty array, it will be used to store your result.
$result = array();
You need to iterate through your initial array, you can use foreach().
Then, given your parent_category_id simply use an if statement to check whether it's the given id or not.
If it is, just construct and push your result to your $result array.
Use any of the sort functions you like
Use the magic return $result;
You're done.
function returnSortedParents($categories, $target_parent){
$new_list = array();
foreach($categories as $index => $array){
//FIND ONLY THE ELEMENTS MATCHING THE TARGET PARENT ID
if($array['parent_category_id']==$target_parent){
$new_list[$index = $array['sort_order'];
}
return asort($new_list); //SORT BASED ON THE VALUES, WHICH IS THE SORTING ORDER
}