将排序后的数字数组隐含为带逗号的字符串,并将连续整数合并为带连字符的范围表达式


Implode sorted number array to string with commas and merge consecutive integers into hyphenated range expressions

我想内爆一个数组,但有一点不同。我想用-符号合并区间。如何做到这一点?(数组已排序!)

示例:

array(1,2,3,6,8,9) => "1-3,6,8-9"
array(2,4,5,6,8,10) => "2,4-6,8,10"

这应该适用于您:

首先,对于每次迭代,我们只需将当前迭代次数附加到$result字符串:

$result .= $arr[$i];

在此之后,我们在while循环中检查数组(1)中是否存在下一个元素,并且它遵循当前迭代(2)中的数字。我们这样做,直到条件评估为false:

//(1)Check if next element exists     (2)Check if next element follows up the prev one
      ┌───────┴───────┐    ┌───────────┴────────────┐      
while(isset($arr[$i+1]) && $arr[$i] + 1 == $arr[$i+1] && ++$range)
    $i++;

然后我们检查我们是否有一个范围(例如1-3)。如果是,那么我们将短划线和范围的结束号附加到结果字符串:

if($range)
    $result .= "-" . $arr[$i];

最后,我们还检查我们是否在数组的末尾,并且不再需要附加逗号:

if($i+1 < $l)
    $result .= ",";

代码:

<?php
    $arr = array(1,2,3,6,8,9);
    $result = "";
    $range = 0;
    for($i = 0, $l = count($arr); $i < $l; $i++){
        $result .= $arr[$i];
        while(isset($arr[$i+1]) && $arr[$i] + 1 == $arr[$i+1] && ++$range)
            $i++;
        if($range)
            $result .= "-" . $arr[$i];
        if($i+1 < $l)
            $result .= ",";
        $range = 0;   
    }
    echo $result;
?>

输出:

1-3,6,8-9
    $oldArray=array(2,4,5,6,8,10);
    $newArray=array();

    foreach($oldArray as $count=>$val){
        if($count==0){
            //begin sequencing
            $sequenceStart=$sequenceEnd=$val;
        }
        if($val==$sequenceEnd+1){
            $sequenceEnd=$val;
            continue;
        }else{
            if($sequenceEnd==$val){
                //do nothing
                continue;
            }

        }
        //new sequence begins 
        //save new sequence
        if($sequenceStart==$sequenceEnd){
            //sequnce is a single number
            $newArray[]=$sequenceEnd;
        }else{
            $newArray[]=$sequenceStart.'-'.$sequenceEnd;
        }
        //reset sequence
        $sequenceStart=$sequenceEnd=$val;
    }
    //new sequence begins 
    //save new sequence
    if($sequenceStart==$sequenceEnd){
        //sequnce is a single number
        $newArray[]=$sequenceEnd;
    }else{
        $newArray[]=$sequenceStart.'-'.$sequenceEnd;
    }
    //reset sequence
    $sequenceStart=$sequenceEnd=$val;

    return implode(',', $newArray);

没有这样的函数,因此您需要自己创建一个。我刚刚创建了一个示例函数,它可能看起来是什么样子,有很多可能的解决方案(如果它真的有效,就没有尝试,因为我在reach-atm中没有Web服务器)

<?php
function implodeNumberArray($arr) {
 $lastValue = NULL;
 $o = "";
 //For each value in array
 foreach ($arr as $v) {
  if(!is_null($lastValue)) {
   //If the number is following, do not paste it
   if(($lastValue+1) == $v) {
    //Check if the - sign was already posted
    if(!(stripos(strrev($o), '-') === 0)) {
     // - sign not pasted, therefore paste it
     $o .= "-";
    }
   } else {
    //Check if there is a - sign at the end
    if((stripos(strrev($o), '-') === 0)) {
     // Has - => paste 'prevValue,value''
     $o .= $lastValue . "," . $v;
    } else {
     //Check if there is a , sign at the end
     if((stripos(strrev($o), ',') === 0)) {
      // No - but , => paste 'value'
      $o .= $v;
     } else {
      // No - and no , => paste ',value'
      $o .= ",".$v;
     }         
    }
   }
  } else {
   $o = $v;
  }
  $lastValue = $v;
 }
 //Check if the implode has the last number set correctly
 if((stripos(strrev($o), '-') === 0)) {
  $o .= $lastValue;
 }
 return $o;
}
echo implodeNumberArray(array(1,2,3,6,8,9));
?>

类似于答案@通过从连续月份创建连字符表达式来减少月份名称数组

如果数组为空或数字没有紧跟在前一个数字后面,则将数字作为引用推送到结果数组中。

当遇到连续数字时,通过保留前导数字并添加新连字符和新数字来重新生成引用字符串。

只需要一个循环和一个条件表达式。

代码:(演示)

function hyphenatedRanges(array $numbers): string
{
    $result = [];
    foreach ($numbers as $i => $number) {
        if (isset($ref) && $number === $numbers[$i - 1] + 1) {
            $ref = strtok($ref, "-") . "-$number";
        } else {
            unset($ref);
            $ref = $number;
            $result[] = &$ref;
        }
    }
    return implode(',', $result);
}
echo hyphenatedRanges([1, 2, 3, 6, 8, 9]) . "'n"; // "1-3,6,8-9"
echo hyphenatedRanges([2, 4, 5, 6, 8, 10]); // "2,4-6,8,10"