对每个子数组中的项目进行计数,以生成唯一键和计数的关联数组

Count items in each subarray to produce an associative array of unique keys and counts

提问人:DanielAttard 提问时间:11/27/2011 最后编辑:mickmackusaDanielAttard 更新时间:9/13/2023 访问量:55051

问:

从下面的数组中可以看出,有三个元素出现在 11 月 18 日,另外两个元素出现在 11 月 22 日。有人可以告诉我如何从这个数组中分别检索 3 和 2 的计数吗?基本上,我想最终得到这样的结果:

2011年11月18日 = 3项

2011年11月22日 = 2项

当然,日期和不同日期的数量每次都会有所不同。下面是数组:

[
    [
        ['2011-11-18 00:00:00' => 'C'],
        ['2011-11-18 00:00:00' => 'I'],
        ['2011-11-18 00:00:00' => 'S']
    ],
    [
        ['2011-11-22 00:00:00' => 'C'],
        ['2011-11-22 00:00:00' => 'S']
    ]
]
PHP 多维数组 reduce 计数

评论

0赞 hafichuk 11/27/2011
您是否关心每个日期中的值?(即C,I,S,C,S)
0赞 DanielAttard 11/27/2011
现在我没有,但很快我会,所以我可能也应该尝试跟踪这些值。谢谢。
0赞 MeLight 11/27/2011
所以你需要一个二维数组,以日期为键,并为每个日期提供一个相关值的数组?

答:

9赞 Godwin 11/27/2011 #1

这适用于您的需求吗?

$dates = array(array(array("2011-11-18 00:00:00" => C), array("2011-11-18 00:00:00" => I),array
("2011-11-18 00:00:00" => S)),
array(array("2011-11-22 00:00:00" => C), array("2011-11-22 00:00:00" => S)));

$date_count = array();  // create an empty array

foreach($dates as $date) {  // go thought the first level
    foreach($date as $d) {  // go through the second level
        $key = array_keys($d);  // get our date
        // here we increment the value at this date
        // php will see it as 0 if it has not yet been initialized
        $date_count[$key[0]]++;
    }
}
    // show what we have
print_r($date_count);

指纹:

Array ( [2011-11-18 00:00:00] => 3 [2011-11-22 00:00:00] => 2 )

注意:这假设您在构建数组时将始终获取数据,并且每个日期的格式相同。如果您不能假设每个日期都将被格式化,这将是使用 date() 函数的简单转换。如果你不能假设你会得到完全这样的结构数据,那么解决这个问题的最好方法可能是通过递归函数。

评论

1赞 Godwin 11/27/2011
太好了,如果您有任何问题,请告诉我。关键的事情(没有双关语的意思)是数组存储以日期为键,以数字为值的值。每次我们看到该日期时,该值都会递增。
2赞 Sylverdrag 11/27/2011 #2

假设您的数组示例具有代表性:

foreach ($array as $key => $value)
{
   echo count($value) . "<br />";
}

将回显每个主数组项中的数组数。在您的示例中,这也是每个日期的条目数。

这当然不会检查日期本身

1赞 hafichuk 11/27/2011 #3

您可以使用 array_walk_recursive() 访问数组结构中的所有叶节点。

与此类似的东西应该对你有用:

<?php

$data = array(
 array(
  array('2011-11-18 00:00:00' => 'C'),
  array('2011-11-18 00:00:00' => 'I'),
  array('2011-11-18 00:00:00' => 'S')),
 array(
  array('2011-11-22 00:00:00' => 'C'),
  array('2011-11-22 00:00:00' => 'S')));

function countleafkeys($value, $key, $userData)
{
  echo "$key\n";
  if(!isset($userData[$key])) {
    $userData[$key] = 1;
  } else {
    $userData[$key]++;
  }
}

$result = array();
array_walk_recursive($data, 'countleafkeys', &$result);

print_r($result);

输出:

2011-11-18 00:00:00
2011-11-18 00:00:00
2011-11-18 00:00:00
2011-11-22 00:00:00
2011-11-22 00:00:00
Array
(
    [2011-11-18 00:00:00] => 3
    [2011-11-22 00:00:00] => 2
)

评论

0赞 Mahmoud Gamal 11/27/2011
+1 使用,顺便说一句:这种技术是不是某种 en.wikipedia.org/wiki/Lambda_lifting??array_walk_recursive()
0赞 hafichuk 11/28/2011
@MGA 谢谢!老实说,Lambda 提升对我来说是一个新术语,所以你(目前)可能更能判断它是否是。感谢您的睡前阅读!
3赞 Kaii 11/27/2011 #4

发布的答案对于您的代表性示例是正确的,但我想添加另一个解决方案,无论您创建多少个嵌套数组,它都可以工作。它以递归方式迭代数组,并计算所有子数组中的所有项目。

它返回数组中项的总数。在第二个参数中,您可以指定一个数组 引用,它将包含(嵌套)数组中每个唯一键的计数。

例:

<?php
$deeply_nested = array(
                     'a' => 'x',
                     'b' => 'x',
                     'c' => 'x',
                     'd' => array(
                         'a' => 'x',
                         'b' => 'x',
                         'c' => array(
                             'a' => 'x',
                             'b' => 'x'
                         ),
                         'e' => 'x'
                    ) 
                );

function count_nested_array_keys(array &$a, array &$res=array()) {
    $i = 0;
    foreach ($a as $key=>$value) {
        if (is_array($value)) {
             $i += count_nested_array_keys($value, &$res);
        }
        else {
             if (!isset($res[$key]) $res[$key] = 0;

             $res[$key]++;
             $i++;
        }
    }
    return $i;
}

$total_item_count = count_nested_array_keys($deeply_nested, $count_per_key);

echo "total count of items: ", $total_item_count, "\n";
echo "count per key: ", print_r($count_per_key, 1), "\n";

结果是:

total count of items: 8
count per key: Array
(
    [a] => 3
    [b] => 3
    [c] => 1
    [e] => 1
)

评论

0赞 hakre 11/28/2011
@Kaii:您可能也对这种递归遍历方式感兴趣: stackoverflow.com/a/8295478/367456 - 请参阅第二个代码示例。
0赞 mintobit 11/27/2011 #5

这是我的递归变体:

$arr = array(
    '0' => array(
        '0' => array('2011-11-18 00:00:00' => 'C'),
        '1' => array('2011-11-18 00:00:00' => 'I'),
        '2' => array('2011-11-18 00:00:00' => 'S')
    ),
    '1' => array(
        '0' => array('2011-11-22 00:00:00' => 'C'),
        '1' => array('2011-11-22 00:00:00' => 'S')
    ),
    '2' => array(
        '0' => array(
            '0' => array('2011-11-22 00:00:00' => 'D')
        )
    )
);

function count_values($array, &$result = array(), $counter = 0)
{
    foreach ($array as $key => $data)
    {
        if (is_array($data))
        {
            count_values($data, $result, $counter);
        }
        else
        {
            array_key_exists($key, $result) ? $result[$key]++ : $result[$key] = 1;
        }
    }

    return $result;
}

print_r(count_values($arr));

这将返回:

Array ( [2011-11-18 00:00:00] => 3 [2011-11-22 00:00:00] => 3 )
2赞 hakre 11/28/2011 #6

对于您的特定结构,我认为最精简的方法是使用然后获取日期值和每个值:$arrayforeachcount()

$dateCounts = array();
foreach($array as $date)
{
    $dateCounts[key($date[0])] = count($date);
}
var_dump($dateCounts);

有了你,这给了:$array

array(2) {
  ["2011-11-18 00:00:00"]=> int(3)
  ["2011-11-22 00:00:00"]=> int(2)
}

如果你正在寻找一种更通用的方法,你可以利用并遍历所有叶键/值元素,然后只计算键:RecursiveArrayIteratorRecursiveIteratorIterator

$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$keyCounts = array();
foreach ($it as $key => $value)
{
    isset($keyCounts[$key]) ? $keyCounts[$key]++ : $keyCounts[$key] = 1; 
} 
var_dump($keyCounts);

希望这会有所帮助。

评论

0赞 mickmackusa 9/2/2023
另一种功能风格等价物:3v4l.org/s7ZUR
29赞 emilie zawadzki 2/7/2014 #7

您可以使用:

count($array, COUNT_RECURSIVE);

计算嵌套数组树中的叶子数

评论

0赞 mickmackusa 9/2/2023
这个答案看起来根本没有帮助/相关。
0赞 emilie zawadzki 9/11/2023
@mickmackusa 这个答案是投票最多的,所以我想它很有帮助/相关。不要犹豫,尝试不要只看一眼;)
0赞 mickmackusa 9/12/2023
我在这里待了足够长的时间,可以找到许多被点赞但没有回答所提出的问题。这意味着读者不知道如何投票或不知道他们需要什么。这个未煮熟的答案绝对不能提供预期的结果。
0赞 apokryfos 9/17/2023
没有解释递归如何帮助解决这个问题。以下是在问题输入上运行此代码时的结果。它只是给出了一个“12”(这是出乎意料的)。如果@emiliezawadzki至少能解释这个答案如何帮助解决原始问题,我将不胜感激(几句话不会有什么坏处)。count
1赞 itsazzad 12/11/2015 #8
<?php
$count0=count($array[0], COUNT_RECURSIVE)-count($array[0]);
$count1=count($array[1], COUNT_RECURSIVE)-count($array[1]);

评论

1赞 cottton 8/25/2021
对于二维数组计数来说,这是一个非常好的解决方案。要获取总数,请执行以下操作: .(如果数组为空)(编辑:我知道这是 100% 的主题,但值得一提的是 imo)max( 0, count($array, COUNT_RECURSIVE) - count($array) )max(0, ...)
-1赞 user4272288 10/25/2017 #9

如果您想计算一维和二维的项目,您可以尝试:

echo 'Size of unidimensional is: '.count($celda).'<br/>';

echo 'Size of bidimensional is: '.count($celda[0]).'<br/>';