我有以下数组:
(
[25] => 1
[26] => 3
[10] => 2
[24] => 1
)
它是使用PHP中的array_count_values()
函数创建的。
在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] =>
)
这些是年龄,所以我如何将这些分组到年龄组?
假设我想要以下年龄段:<= 18
19-26
27-32
> 32
它应该看起来:
(
[<= 18] => 1
[19-26] => 4
[27-32] => 2
[ > 32] => 1
)
这是否有现成功能?
我的解决方案:
1繁琐的方法是创建年龄组的变量。如果密钥匹配范围($min <= $value) && ($value <= $max)
...
答案 0 :(得分:9)
有趣的问题。这是我的解决方案。首先,定义一个年龄范围数组:
$age_ranges = array(
array( 0, 18),
array( 19, 26),
array( 27, 32),
array( 33, 150) // I use 150 as the "max" age
);
然后,我们有array_count_values()
输出:
$array_count_values = array( 25 => 1, 26 => 3, 10 => 2, 24 => 1); // From OP
现在,我们创建一个包含所有年龄的数组,其中键是年龄,值是具有该年龄的人数。它需要按其键进行排序,以便进行下一步。
$all_ages = $array_count_values + array_fill( 0, 150, 0);
ksort( $all_ages);
最后,我循环遍历所有年龄范围,从$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));
}
print_r( $result);
yields the following output:
Array
(
[0-18] => 2
[19-26] => 5
[27-32] => 0
[33-150] => 0
)
编辑:由于您仍然可以访问原始数组,因此您只需计算最终有多少“未知数”:
$result['unknown'] = count( array_filter( $original_array, function( $el) {
return empty( $el);
}));
答案 1 :(得分: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';
}
所以基本上在这里,我们只是将每个年龄变成它所代表的范围的字符串表示。所以现在我们将有一系列范围,所以我们需要将其减少到摘要(将所有这些范围加起来):
然后是reduce函数:
$reduce = function($result, $age) {
$result[$age]++;
return $result;
}
这很简单。如果你想支持动态范围,那么你在那里有一些逻辑来检查是否未设置年龄(然后将其初始化为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));
然后产生:
array(4) {
["unknown"]=> int(0)
["<= 18"]=> int(3)
["19-26"]=> int(2)
["26-32"]=> int(0)
["> 32"]=> int(2)
}
答案 2 :(得分:1)
如果您只想使用array_count_values()
之前的阵列,可以使用
$ages = array(
0 => 26,
1 => 18,
2 => 28,
3 => 22,
4 => null,
5 => 21,
6 => 26,
7 => null);
创建一个空白数组来填充
$final = array(
'unknown' => 0,
'18' => 0,
'19_26' => 0,
'27_32' => 0,
'32' => 0,
);
array_walk($ages, function($age, $i, $final) {
if (!$age) { $final['unknown']++; return; }
if ($age <= 18) { $final['18']++; return; }
if ($age <= 26) { $final['19_26']++; return; }
if ($age <= 32) { $final['27_32']++; return; }
if ($age > 32) { $final['32']++; return; }
}, &$final);
来自$ final的输出:
array (size=5)
'unknown' => int 2
18 => int 1
'19_26' => int 4
'27_32' => int 1
32 => int 0
答案 3 :(得分:1)
在看到所有这些解决方案之后,我想为什么不将Regex与原始阵列一起使用?
$ages = array(25, 26, 10, 24, 10, 26, 26, 32, 32, 54, 84, 4, 18, 5, 98, 27);
$string = '#'. implode('#', $ages) . '#';
preg_match_all('/(#[0-9]#|#1[0-7]#)|(#1[8-9]#|#2[0-6]#)|(#2[7-9]#|#3[0-2]#)|(#3[3-9]#|#[4-9][0-9]#|#1[0-5][0-9]#)/', $string, $groups);
$age_ranges = array('0-17' => count(array_filter($groups[1])), '18-26' => count(array_filter($groups[2])), '27-32'
=> count(array_filter($groups[3])), '33-159' => count(array_filter($groups[4])));
print_r($age_ranges);
输出:
Array
(
[0-17] => 2
[18-26] => 3
[27-32] => 1
[33-159] => 2
)