7

次の配列があります。

(
    [25] => 1
    [26] => 3
    [10] => 2
    [24] => 1
)

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] =>
)

これらは年齢ですが、これらを年齢グループにグループ化するにはどうすればよいですか?

次の年齢層が必要だとしましょう。<= 18 19-26 27-32 > 32

それは見えるはずです:

(
[<= 18] => 1
[19-26] => 4
[27-32] => 2
[ > 32] => 1
)

このための準備機能はありますか?

私の解決策: 退屈な方法の 1 つは、年齢層の変数を作成することです。キーが範囲と一致する場合、 foreach よりも特定の年齢層の変数 ++ を増やします($min <= $value) && ($value <= $max)...

4

4 に答える 4

10

興味深い問題です。これが私の解決策です。まず、年齢範囲の配列を定義します。

$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));
}

Aprint_r( $result); は次の出力を生成します

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); 
}));
于 2013-03-15T14:16:22.957 に答える
8

これは 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) 
}
于 2013-03-15T15:51:14.397 に答える
1

これらすべてのソリューションを見た後、元の配列で正規表現を使用しないのはなぜだと思いましたか?

$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
)
于 2013-03-15T15:28:14.603 に答える
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
于 2013-03-15T14:27:34.693 に答える