将数组键分组到数字范围,可能吗?

7 php arrays

我有以下数组:

(
    [25] => 1
    [26] => 3
    [10] => 2
    [24] => 1
)
Run Code Online (Sandbox Code Playgroud)

它是使用array_count_values()PHP中的函数创建的.

在array_count_values之前,实际原始数组是这样的......

Array
(
    [0] => 26
    [1] => 
    [2] => 18
    [3] => 28
    [4] => 22
    [5] => 21
    [6] => 26
    [7] => 
    [8] => 
    [9] => 
    [10] => 
    [11] => 
    [12] =>
    [13] =>
    [14] =>
    [15] =>
    [16] =>
    [17] =>
    [18] =>
    [19] =>
    [20] =>
)
Run Code Online (Sandbox Code Playgroud)

这些是年龄,所以我如何将这些分组到年龄组?

让我们说我想要以下年龄组: <= 18 19-26 27-32 > 32

它应该看起来:

(
[<= 18] => 1
[19-26] => 4
[27-32] => 2
[ > 32] => 1
)
Run Code Online (Sandbox Code Playgroud)

有这个准备好的功能吗?

我的解决方案:1繁琐的方法是创建年龄组的变量.如果密钥匹配范围,则比foreach和增加特定年龄组的变量++ ($min <= $value) && ($value <= $max)...

nic*_*ckb 9

有趣的问题.这是我的解决方案.首先,定义一个年龄范围数组:

$age_ranges = array(
    array( 0, 18),
    array( 19, 26),
    array( 27, 32),
    array( 33, 150) // I use 150 as the "max" age
);
Run Code Online (Sandbox Code Playgroud)

然后,我们有你的array_count_values()输出:

$array_count_values = array( 25 => 1, 26 => 3, 10 => 2, 24 => 1); // From OP
Run Code Online (Sandbox Code Playgroud)

现在,我们创建一个包含所有年龄的数组,其中键是年龄,值是具有该年龄的人数.它需要按其键进行排序以进行下一步.

$all_ages = $array_count_values + array_fill( 0, 150, 0);
ksort( $all_ages);
Run Code Online (Sandbox Code Playgroud)

最后,我循环遍历所有年龄范围,从$all_ages数组中切除年龄范围,并将它们的值相加以生成年龄范围的数组,其值对应于落入该年龄范围的人数.

$result = array();
foreach( $age_ranges as $range) {
    list( $start, $end) = $range;
    $result["$start-$end"] = array_sum( array_slice( $all_ages, $start, $end - $start + 1));
}
Run Code Online (Sandbox Code Playgroud)

A print_r( $result); 产生以下输出:

Array
(
    [0-18] => 2
    [19-26] => 5
    [27-32] => 0
    [33-150] => 0
)
Run Code Online (Sandbox Code Playgroud)

编辑:由于您仍然可以访问原始数组,因此您可以计算出最后有多少"未知数":

$result['unknown'] = count( array_filter( $original_array,  function( $el) { 
    return empty( $el); 
}));
Run Code Online (Sandbox Code Playgroud)

  • @HamZaDzCyber​​DeV:我不知道`array_map`在这里会有什么帮助.加上'foreach`可能更快. (2认同)

irc*_*ell 7

这听起来像map-reduce的完美案例.

地图步骤:将每个年龄变成4个范围中的一个.

减少步骤:将范围转换为范围的结果数组.

我们来试试吧:

$map = function($age) {
    if (!$age) {
        return 'unknown';
    } elseif ($age <= 18) {
        return '<= 18';
    } elseif ($age <= 26) {
        return '19-26';
    } elseif ($age <= 32) {
        return '26-32';
    }
    return '> 32';
}
Run Code Online (Sandbox Code Playgroud)

所以基本上在这里,我们只是将每个年龄变成它所代表的范围的字符串表示.所以现在我们将有一系列范围,所以我们需要将其减少到摘要(将所有这些范围加起来):

然后是reduce函数:

$reduce = function($result, $age) {
    $result[$age]++;
    return $result;
}
Run Code Online (Sandbox Code Playgroud)

这很简单.如果你想支持动态范围,那么你在那里有一些逻辑来检查年龄是否未设置(然后将其初始化为0)...

所以现在,把它们放在一起:

$array = array(12, 63, 24, 34, 12, 10, 19,); // Your ages
$data = array_map(function($age) {
    if (!$age) {
        return 'unknown';
    } elseif ($age <= 18) {
        return '<= 18';
    } elseif ($age <= 26) {
        return '19-26';
    } elseif ($age <= 32) {
        return '26-32';
    }
    return '> 32';
}, $array);
$result = array_reduce($data, function($result, $age) {
    $result[$age]++;
    return $result;
}, array('unknown' => 0, '<= 18' => 0, '19-26' => 0, '26-32' => 0, '> 32' => 0));
Run Code Online (Sandbox Code Playgroud)

然后产生:

array(4) { 
    ["unknown"]=> int(0)
    ["<= 18"]=> int(3) 
    ["19-26"]=> int(2) 
    ["26-32"]=> int(0) 
    ["> 32"]=> int(2) 
}
Run Code Online (Sandbox Code Playgroud)