2010-10-28 40 views
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() 

你扔给我。

回答

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. 
} 

Code In Action

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

我认为,排序($列表)是一个错误.. – 2010-10-28 16:35:41

+0

@Jan - 这个问题初始误读 – 2010-10-28 16:50:04

0
$result = array(); 
$word = ''; 
$lastChar = $myList[0]; 
foreach($myList as $char){ 
    if($lastChar !== $char){ 
     $result[] = $word; 
     $word = ''; 
    } 
    $word .= $char 
} 
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); 
+0

您可能会收到未定义偏移-1在代码的第三行,但我非常喜欢这个解决方案。 – 2010-10-28 17:10:37

+0

@ [JanTuroň]你找到了我。诚然,我通过设置错误级别来排除E_NOTICE错误而欺骗了一下。 ;-) – Max 2010-10-28 17:12:48

+0

@ [JanTuroň]我更新了代码,添加了一行,但现在它不会吞下错误,并且不会每次迭代计算两次$ a的长度。 – Max 2010-10-28 17:16:13

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