基于连续出现次数缩短数组

3
我正在学习PHP,遇到了以下与列表相关的问题。语言并不重要,因此我会用伪代码来描述。当然,伪代码答案也可以。
假设有一个包含两个不同的重复元素的列表,例如两个单个字符。因此,我的列表大致如下:
myList = [C, C, D, C, D, D, D, C, C, D, C, D, C, C, ...]

然而,那不是我想要的形式。相反,列表应该像这样:
myList* = [CC, D, C, DDD, CC, D, C, D, CC, ...]
myList* = shorten(myList)

什么是将单字符列表转换为包含连续字符串的元素的最优雅方法?我的解决方案让我感到相当糟糕,因为它涉及多重嵌套if语句、各种状态变量和其他不好的东西。
请提供伪代码!非常感谢任何实现。
shorten()

你向我扔过来的东西。
5个回答

2

使用PHP 5.3闭包和array_reduce

ini_set('error_reporting', E_ALL);

function shorten(array $list) {
    return array_reduce($list, function($a, $b) {
        $lastIdx = count($a) - 1;
        if(isset($a[$lastIdx]) && strstr($a[$lastIdx], $b)) $a[$lastIdx] .= $b;
        else $a[] = $b;

        return $a;
    }, array());
}


$list = array('C', 'C', 'D', 'C', 'D', 'D', 'D', 'C', 'C', 'D', 'C', 'D', 'C', 'C');
$expected = array('CC', 'D', 'C', 'DDD', 'CC', 'D', 'C', 'D', 'CC');

$listShortened = shorten($list);
assert($expected === $listShortened);

你可能会在代码的第三行收到未定义偏移量-1的错误,但我非常喜欢这个解决方案。 - Jan Turoň
@[Jan Turoň] 你抓住我了。没错,我通过设置错误级别来排除 E_NOTICE 错误有点作弊。;-) - Max
@[Jan Turoň] 我更新了代码,添加了一行,但现在它不会忽略错误并且不会在每次迭代中两次计算 $a 的长度。 - Max

0

你可以通过跟踪当前字符和上一个字符,在一次数组扫描中完成这个操作:

function shorten($myList) {
        $myList[] = '';                         // add a dummy char at the end of list.
        $result = array();                      // result to be returned.
        $last_char = $myList[0];                // initilize last char read.
        $combine = $last_char;                  // initilize combined string.
        for($i=1;$i<count($myList);$i++) {      // go from index 1 till end of array.
                $cur_char = $myList[$i];        // current char.
                if($cur_char != $last_char) {   
                        $result[] = $combine;   // time to push a new string into result.
                        $combine = $cur_char;   // reset combine string.
                } else {
                        $combine.=$cur_char;    // is cur char is same as prev..append it.
                }
                $last_char = $cur_char;         // for next iteration cur become last.
        }
        return $result;                         // return result.
}

实战编程


0
$myList = array('C', 'C', 'D', 'C', 'D', 'D', 'D', 'C', 'C', 'D', 'C', 'D', 'C', 'C');

function shorten($list) {
    $newList = array();

    foreach($list as $key => $entry) {
        if ($key == 0) {
            $newList[] = $entry;
        } elseif ($entry == substr($newList[count($newList)-1],0,1)) {
            $newList[count($newList)-1] .= $entry;
        } else {
            $newList[] = $entry;
        }
    }

    return $newList;
}

$shortenedList = shorten($myList);

var_dump($myList);
echo '<br />';
var_dump($shortenedList);

0
$result = array();
$word = '';
$lastChar = $myList[0];
foreach($myList as $char){
    if($lastChar !== $char){
        $result[] = $word;
        $word = '';
    }
    $word .= $char
}

0
一个比Max的回答稍微短一点的替代方案...
$mylist = array("a","b","b","b","c","c","d");
function shorten($array) {
  $str = implode("",$array); // step 1: make string from array of chars
  preg_match_all("/(\w)\\1*/",$str,$matches); // step 2: split into chunks
  return $matches[0]; // step 3: that's all
}
print_r(shorten($mylist));

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