12

私はこのような配列を持っています:

$arr = array(1, 1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3);

関数を見つけましたarray_count_values()が、同じ値をすべてグループ化し、連続するシーケンスの中断を考慮せずに発生をカウントします。

$result[1] = 5
$result[2] = 4
$result[3] = 3

連続する値の各セットをグループ化し、各シーケンスの長さをカウントするにはどうすればよいですか?1番号、、、2およびの2つのシーケンスセットがあることに注意してください3

私が生成することを期待しているデータは、これに似ている必要があります。

[1] = 3;
[2] = 2;
[3] = 2;
[1] = 2;
[2] = 2;
[3] = 1;
4

6 に答える 6

15

手動で簡単に行うことができます。

$arr = array(1,1,1,2,2,3,3,1,1,2,2,3);

$result = array();
$prev_value = array('value' => null, 'amount' => null);

foreach ($arr as $val) {
    if ($prev_value['value'] != $val) {
        unset($prev_value);
        $prev_value = array('value' => $val, 'amount' => 0);
        $result[] =& $prev_value;
    }

    $prev_value['amount']++;
}

var_dump($result);
于 2011-03-10T04:03:27.950 に答える
7

PHPのarray_count_values関数はどうですか?

<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>

出力:

Array
(
    [1] => 2
    [hello] => 2
    [world] => 1
)
于 2016-05-28T15:22:21.730 に答える
3

私の提案は、ループに入る前に配列から最初の値を抽出して削除し、一時的な配列($carry)を使用して、新しい値がそれぞれキャリー配列のキーと一致するかどうかを追跡することです。もしそうなら、それをインクリメントします。そうでない場合は、完了したシーケンスカウントを結果配列にプッシュし、キャリーを新しい値で上書きして、カウンターを1に設定します。ループが終了したら、残りのキャリーを結果セットにプッシュします。私のスニペットは、入力配列が空かどうかをチェックしません。必要に応じて、その条件をプロジェクトに追加します。

コード:(デモ

$array = [1,1,1,2,2,3,3,1,1,2,2,3];
 
$result = [];
$carry = [array_shift($array) => 1];
 
foreach ($array as $value) {
    if (isset($carry[$value])) {
        ++$carry[$value];
    } else {
        $result[] = $carry;
        $carry = [$value => 1];
    }
}
$result[] = $carry;
print_r($result);

出力:(ページの肥大化を減らすために圧縮されます)

[
    [1 => 3],
    [2 => 2],
    [3 => 2],
    [1 => 2],
    [2 => 2],
    [3 => 1],
]

zerkmsスタイルの参照による変更スタイルの手法を実装する場合は、次のスニペットで上記のスニペットと同じ結果が得られます。

事実上、新しく検出されたすべての値を、関連する単一要素の配列として、インデックス付きの結果配列にプッシュします。プッシュされたサブ配列は変数($carry)として宣言され、参照によって結果配列に割り当てられる(= &)ため、の増分は$carry結果配列内の深くネストされた値に適用されます。出力配列には、複数回発生する特定の値を確実に格納できるように、構造に追加の深さが必要です。

コード:(デモ

$result = [];
$carry = [];
foreach ($array as $value) {
    if ($carry && key($carry) === $value) {
        ++$carry[$value];
    } else {
        unset($carry);
        $carry = [$value => 1];
        $result[] = &$carry;
    }
}
unset($carry);
print_r($result);

ループの後で参照変数を設定解除する$carry必要はないかもしれませんが、変数のスコープ内でその変数が再利用される可能性がある場合は、参照を。で切り離すことが重要になりますunset()

そして、楽しみのために、サンプルデータで機能する恐ろしい正規表現を取り入れたアプローチを次に示します。デモ

于 2020-05-30T08:01:47.953 に答える
1
$current = null;
foreach($your_array as $v) {
    if($v == $current) {
        $result[count($result)-1]++;
    } else {
        $result[] = 1;
        $current = $v;
    }
}

var_dump($result);
于 2011-03-10T04:04:42.737 に答える
0
function findRepetitions($times, $array) {

    $values = array_unique($array);

    $counts = [];
    foreach($values as $value) {
        $counts[] = ['value' => $value, 'count' => 0];
    }

    foreach ($array as $value) {
        foreach ($counts as $key => $count) {
            if ($count['value'] === $value) {
                $counts[$key]['count']++;
            }
        }
    }

    $repetitions = [];
    foreach ($counts as $count) {
        if ($count['count'] === $times) {
            $repetitions[] = $count['value'];
        }
    }

    return $repetitions;
}
于 2015-01-24T12:06:09.740 に答える
-1

これが私がそれをする方法です:

function SplitIntoGroups($array)
{
    $toReturnArray = array();
    $currentNumber = $array[0];
    $currentCount = 1;
    for($i=1; $i <= count($array); $i++)
    {
        if($array[$i] == $currentNumber)
        {
            $currentCount++;
        }
        else
        {
            $toReturnArray[] = array($currentNumber, $currentCount);
            $currentNumber = $array[$i];
            $currentCount = 1;
        }
    }

    return $toReturnArray;
}

$answer = SplitIntoGroups(array(1,1,1,2,2,3,3,1,1,2,2,3));
for($i=0; $i<count($answer); $i++)
{
    echo '[' . $answer[$i][0] . '] = ' . $answer[$i][1] . '<br />';
}
于 2011-03-10T04:13:20.447 に答える