在数组中删除连续的重复元素

5
我正在处理一个函数,它可以去除数组中的重复元素。 这个函数的特殊之处在于,如果连续的重复元素少于5个,就会保留,而大于等于5个的则会变成一个单独的数字。
我的问题是无法想出正确的逻辑。
希望你能帮我解决这个问题。
谢谢。 示例代码
function removeDuplicates($array){
        $result = array();
        $lastVal = null;
        $temp_array = array();
        foreach ($array as $key => $value) {
            # code...
            if($value != $firstVal){

                $result[] = $value;   

            }else{

                $temp_array[] = $value;

            }

            $lastVal = $value;

        }

        return $result;

    }

样例

$array = array(1,2,4,1,1,1,1,0,8,7,2,0,0,8,8,8,8,8,8,8,2,4,1,5);

预期结果
[1,2,4,1,1,1,1,0,8,7,2,0,0,8,2,4,1,5]

你的代码中的 $firstVal 是什么? - MorganFreeFarm
4个回答

3

这里:

    <?php

    $array = array(1,2,4,1,1,1,1,0,8,7,2,0,0,8,8,8,8,8,8,8,2,4,1,5);
    $test = removeDuplicates($array);
    echo '<pre>';
    var_dump($test);


function removeDuplicates($array){
    $result = [];
    $count = 1;

    for ($i = 1; $i <= count($array)-1; $i++) {
        if ($array[$i] == $array[$i - 1]) {
            $count++;
        } else {
            if ($count >= 5) {
                array_splice($array, $i-$count, $count-1);
            }
            $count = 1;
        }
    }

    return $array;

}

输出:

array(18) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(4)
  [3]=>
  int(1)
  [4]=>
  int(1)
  [5]=>
  int(1)
  [6]=>
  int(1)
  [7]=>
  int(0)
  [8]=>
  int(8)
  [9]=>
  int(7)
  [10]=>
  int(2)
  [11]=>
  int(0)
  [12]=>
  int(0)
  [13]=>
  int(8)
  [14]=>
  int(2)
  [15]=>
  int(4)
  [16]=>
  int(1)
  [17]=>
  int(5)
}

这将适用于"小于5时保留,大于等于5时"的情况,您可以发送第二个变量以使其动态化。 - MorganFreeFarm
1
你能测试一下这些吗:[1,2,4,1,1,1,1,1,0,8,7,2,0,0,8,2,4,1,5][1,2,4,1,1,1,1,1,0,8,7,2,0,0,8,8,8,8,8,8,8,2,4,1,5][1,2,4,1,1,1,1,0,8,7,2,0,0,8,8,8,2,4,1,1,1,1,1,1,5]...? - GMarco24
我并不是因为重置$count的错误而给你投了反对票。你在array_splice($array, $i-$count, $count-1);这一行中也犯了逻辑错误。现在看起来没问题了,所以我把赞投回去了。 - GMarco24
它纯属意外地匹配了预期输出!:D 当您的计数器没有重置时,它在[1,1,1,1]中计数到4,然后在[0,0]中计数到5,然后向前从当前$i位置开始移除那些八个:D :D :D。这是您的代码array_splice($array, $i, $count+1); - GMarco24

3
<?php

function removeDuplicates($array){
    $freq = 5;

    $result = [];
    $size = count($array);

    $counts = [];
    for($i=0;$i<$size;++$i) $counts[] = 0;

    $counts[$size-1] = 1;

    for($i=$size-2;$i>=0;--$i){
        $counts[$i] = 1;
        if($array[$i] === $array[$i+1]) $counts[$i] = $counts[$i+1] + 1;            
    }

    for($i=0;$i<$size;++$i){
        $result[] = $array[$i];
        if($counts[$i] >= $freq){
            $i += $counts[$i] - 1; 
        }
    }

    return $result;
}

$array = array(1,2,4,1,1,1,1,0,8,7,2,0,0,8,8,8,8,8,8,8,2,4,1,5);

print_r(removeDuplicates($array));

演示: https://3v4l.org/mvjOq

  • 上述算法为O(n)算法(使用O(n)额外空间),我们首先预计算当前数字连续出现的次数。

  • 现在,当我们再次迭代时,我们检查当前数组的数字是否具有count value >= frequency。 这里,频率为5

  • 如果计数小于频率,则通常进行迭代。否则,我们直接跳到下一个值得处理的数字,并利用存储在$count[$i]中的频率来帮助处理。即使您要选择的频率为1000或更高,这也可以正常工作。


2
对我来说,这似乎是唯一可行的解决方案。我不知道是否应该对其他所有内容进行更多的踩,但我已经点赞了这个。 - GMarco24
1
这是我所遇到的唯一有效的解决方案。但如果键是关联的,它将丧失原始键。对于数字键的解决方案是使用$result[$i]。如果键是字母数字,则我的建议不适用。 - rlcabral

0
作为一个选项
removeDuplicates(array(1,2,4,1,1,1,1,0,8,7,2,0,0,8,8,8,8,8,8,8,2,4,1,5));

function removeDuplicates($arr){
    $count_duplicates = 0;
    foreach ($arr as $key => $item){
        if($item == $arr[$key+1]){
            $count_duplicates++;
        }else{
            if($count_duplicates >= 5){
                for($i = 0; $i < $count_duplicates; $i++){
                    unset($arr[$key-$i]);
                }
            }
            $count_duplicates = 0;
        }
    }
    return $arr;
}

谢谢您的回答,这行代码 if($item == $arr[$key+1]){ 存在未定义的偏移量。 - user123
$arr[$key+1] - 是数组的下一个元素,在这一刻,如果 $item == $arr[$key+1],我们检查当前元素和下一个元素的相似性。 - Дмитрий Горный

-2

代码应该长这样

$array = array("1", "2", "3", "4", "5", "4", "2", "1");

$result = array_unique($array);


你检查过你的代码了吗?它不是 OP 想要的。(我没有点踩) - nice_dev
输出结果与 OP 想要的不符。他不仅想要唯一的元素。 - nice_dev
请仔细阅读问题。从问题中可以看出,如果连续重复的数字少于5个,则它们将保留不变,而5个或以上的连续重复数字将被合并为一个数字。 - Rahul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接