简体   繁体   中英

Counting items in each category of a multidimensional array

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.

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

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.

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/>";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM