我的建议是在进入循环之前从数组中提取和删除第一个值,并使用临时数组 ( $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()
.
只是为了好玩,这里有一个可怕的正则表达式注入方法,它适用于示例数据:Demo