Converting array elements into range in php

后端 未结 7 1871
时光说笑
时光说笑 2021-01-02 11:39

I’m working on an array of numeric values.

I have a array of numeric values as the following in PHP

11,12,15,16,17,18,22,23,24

And

7条回答
  •  独厮守ぢ
    2021-01-02 12:30

    Just adding my copy that is slightly different and supports a few extra things. I came here to compare it against other implementations. Here is test code to check the capability/correctness of my code:

    $tests = [
        '1, 3, 5, 7, 9, 11, 13-15' => [1, 3, 5, 7, 9, 11, 13, 14, 15],
        '1-5'                      => [1, 2, 3, 4, 5],
        '7-10'                     => [7, 8, 9, 10],
        '1-3'                      => [1, 2, 3],
        '1-5, 10-12'               => [1, 2, 3, 4, 5, 10, 11, 12],
        '1-5, 7'                   => [1, 2, 3, 4, 5, 7],
        '10, 12-15'                => [10, 12, 13, 14, 15],
        '10, 12-15, 101'           => [10, 12, 13, 14, 15, 101],
        '1-5, 7, 10-12'            => [1, 2, 3, 4, 5, 7, 10, 11, 12],
        '1-5, 7, 10-12, 101'       => [1, 2, 3, 4, 5, 7, 10, 11, 12, 101],
        '1-5, 7, 10, 12, 14'       => [1, 2, 3, 4, 5, 7, 10, 12, 14],
        '1-4, 7, 10-12, 101'       => '1,2,3,4,7,10,11,12,101',
        '1-3, 5.5, 7, 10-12, 101'  => '1,2,3,5.5,7,10,11,12,101',
    ];
    
    foreach($tests as $expectedResult => $array) {
        $funcResult = Utility::rangeToStr($array);
        if($funcResult != $expectedResult) {
            echo "Failed: result '$funcResult' != test check '$expectedResult'\n";
        } else {
            echo "Passed!: '$funcResult' == '$expectedResult'\n";
        }
    }
    

    The meat and potatoes, this is meant to be called statically within a class howver simply remove "static public" to use as a normal procedural function:

    /**
     * Converts either a array of integers or string of comma-separated integers to a natural english range, such as "1,2,3,5" to "1-3, 5".  It also supports
     * floating point numbers, however with some perhaps unexpected / undefined behaviour if used within a range.
     *
     * @param string|array $items    Either an array (in any order, see $sort) or a comma-separated list of individual numbers.
     * @param string       $itemSep  The string that separates sequential range groups.  Defaults to ', '.
     * @param string       $rangeSep The string that separates ranges.  Defaults to '-'.  A plausible example otherwise would be ' to '.
     * @param bool|true    $sort     Sort the array prior to iterating?  You'll likely always want to sort, but if not, you can set this to false.
     *
     * @return string
     */
    static public function rangeToStr($items, $itemSep = ', ', $rangeSep = '-', $sort = true) {
        if(!is_array($items)) {
            $items = explode(',', $items);
        }
        if($sort) {
            sort($items);
        }
        $point = null;
        $range = false;
        $str = '';
        foreach($items as $i) {
            if($point === null) {
                $str .= $i;
            } elseif(($point + 1) == $i) {
                $range = true;
            } else {
                if($range) {
                    $str .= $rangeSep . $point;
                    $range = false;
                }
                $str .= $itemSep . $i;
            }
            $point = $i;
        }
        if($range) {
            $str .= $rangeSep . $point;
        }
    
        return $str;
    }
    

提交回复
热议问题