【问题标题】:How to count the consecutive duplicate values in an array?如何计算数组中连续的重复值?
【发布时间】:2011-07-12 10:25:41
【问题描述】:

我有一个这样的数组:

$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 和 3 有两组序列。

我期望生成的数据需要类似于:

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

【问题讨论】:

  • 这不是一个有效的数组,因为键必须是唯一的
  • 怎么样:1 -number=>1 count=>3, 2 number=>2 count=>2 ....
  • @Dagon,我认为这就是他关于二维数组或使用 => 语句的意思。
  • 这称为游程编码。

标签: php arrays duplicates grouping counting


【解决方案1】:

可以简单地手动完成:

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

【讨论】:

  • 除了这是一个纯代码答案之外,为什么有人会 DV 这个正确而聪明的解决方案? ...但最高票数的答案可证明是不正确的。抱歉 Stack Overflow ——选民在这个页面上让你失望了。如果有解释,我可能会紫外线它。
【解决方案2】:

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
)

【讨论】:

  • @ClainDsilva 虽然¯\_(ツ)_/¯返回错误答案
  • 我不知道为什么这么多人赞成这个错误的答案。换个说法,这是对另一个问题的正确答案。
【解决方案3】:

我的建议是在进入循环之前从数组中提取和删除第一个值,并使用临时数组 ($carry) 来跟踪每个新值是否与进位数组中的键匹配。如果是这样,增加它。如果不是,则将完成的序列计数推入结果数组并用新值覆盖进位并将计数器设置为 1。当循环结束时,将延迟进位推入结果集中。我的 sn-p 不检查输入数组是否为空;如有必要,将该条件添加到您的项目中。

代码:(Demo)

$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 样式、按引用修改样式的技术,则以下 sn-p 提供与上述 sn-p 相同的结果。

实际上,它将每个新遇到的值作为关联的单元素数组推送到索引结果数组中。因为推入的子数组被声明为变量 ($carry),然后通过引用 (= &amp;) 分配给结果数组,$carry 的增量将应用于结果数组中深度嵌套的值。输出数组在其结构中需要额外的深度,以便可以可靠地存储多次出现的给定值。

代码:(Demo)

$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() 解耦很重要。

只是为了好玩,这里有一个可怕的正则表达式注入方法,适用于示例数据:Demo

【讨论】:

    【解决方案4】:
    $current = null;
    foreach($your_array as $v) {
        if($v == $current) {
            $result[count($result)-1]++;
        } else {
            $result[] = 1;
            $current = $v;
        }
    }
    
    var_dump($result);
    

    【讨论】:

    • 为您的解决方案提供的一条线是 $result = explode( ',' , implode(',', array_count_values($your_array) ) );
    • 这个答案失去了给定序列中重复的数字与序列长度之间的关系。 Amber,请仅改进此代码答案。
    【解决方案5】:
    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;
    }
    

    【讨论】:

    • 这个纯代码的答案需要它的解释。为什么会有$times 参数?
    【解决方案6】:

    这是我的做法:

    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 />';
    }
    

    【讨论】:

    • 永远不要在 for 循环中使用 count($array),它是在每个循环中计算的,foreach() 在 php 中的数组中是一个更好的循环结构
    • 此 sn-p 生成未定义的偏移量通知,不应使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多