4

配列に次の数列があるとしましょう。

$numbers = array(1,3,2,23,24,25,26, 8)

たとえば、範囲内でそれらを印刷するにはどうすればよいですか。

番号は1〜3、23〜26、8です。

4

7 に答える 7

12

これが簡単なバージョンで、groups範囲を含めて作成します

<?php
$numbers = array(1,3,2,23,24,25,26,8);
sort($numbers);
$groups = array();

for($i = 0; $i < count($numbers); $i++)
{
    if($i > 0 && ($numbers[$i - 1] == $numbers[$i] - 1))
        array_push($groups[count($groups) - 1], $numbers[$i]);
    else // First value or no match, create a new group
        array_push($groups, array($numbers[$i])); 
}

foreach($groups as $group)
{
    if(count($group) == 1) // Single value
        echo $group[0] . "\n";
    else // Range of values, minimum in [0], maximum in [count($group) - 1]
        echo $group[0] . " - " . $group[count($group) - 1] . "\n";
}

出力は

1 - 3
8
23 - 26

さて、質問で説明したように、範囲の順序が重要な場合でも、グループを並べ替えることができます...私が見ることができるものから、最初に範囲に続いて単一の値が必要ですか?これは、追加することで実行できます

function groupRanges($a, $b)
{
    if(count($a) == 1)
        if(count($b) == 1)
            return 0; // equal
        else
            return 1; // so $b is considered less than

    if(count($b) == 1)
        return -1; // so $a is considered less than

    return 0; // both are ranges, keep them there... could be adjusted to compare the size of each range
}

usort($groups, "groupRanges");

の直前foreachで、出力は次のようになります。

1 - 3
23 - 26
8
于 2012-11-27T20:50:28.000 に答える
1
$numbers = array(1,3,2,23,24,25,26,8);

$result = array();

$sorted = $numbers;
sort($sorted);

$current = null;
foreach ($sorted as $v) {
    if (is_null($current)) {
        $current = array($v, $v);
    } else {
        if ($current[1] + 1 == $v) {
            $current[1] = $v;
        } else {
            $result[] = $current;
            $current = array($v, $v);
        }
    }
}

$result[] = $current;

$arranged = array();

foreach ($numbers as $v) {
    foreach ($result as $k => $r) {
        if ($v >= $r[0] && $v <= $r[1]) {
            $arranged[] = $r;
            unset($result[$k]);
            break;
        }
    }
}

var_dump($arranged);

http://ideone.com/i2YGod

于 2012-11-27T20:45:25.130 に答える
1

私はパーティーに少し遅れていることを知っていますが、私はそれをしなければなりませんでした。

<?php
$numbers = array(1,3,2,23,24,25,26,8);
sort($numbers);
$x=0;
$output = array();
foreach($numbers as $k=>$n){
    if(isset($numbers[$k+1]) && $numbers[$k+1]==$n+1){
        $output[$x][]=$n;
    }elseif(isset($output[$x][count($output[$x])-1]) && $output[$x][count($output[$x])-1]+1==$n){
        $output[$x][]=$n;
    }else{
        $x++;
        $output[$x][] = $n;
        $x++;
    }
}
foreach($output as $o){
    echo $o[0];
    if(isset($o[count($o)-1]) && $o[count($o)-1]!=$o[0]){
        echo ' - '.$o[count($o)-1];
    }
    echo '<br>';
}?>
于 2012-11-27T20:58:43.013 に答える
1

昨日投稿できなかったので遅刻しました。それを共有するのに十分エレガントだと思った。

<?php

$numbers = array(1, 3, 2, 23, 24, 25, 26, 8);
sort($numbers);
$result = array();

while (count($numbers) > 0)
{
    $begin = reset($numbers);
    $end = array_shift($numbers);

    while (in_array($end + 1, $numbers))
    {
        $end = array_shift($numbers);
    }
    $beginAndEnd = array_unique(array($begin, $end));
    $result[] = implode('-', $beginAndEnd);
}
var_dump($result);
?>
于 2012-11-28T08:49:06.360 に答える
0

まず、配列、たとえば配列を並べ替えますA。次に、その上で二分探索を行います。配列のサイズが次のようになりますn

A[n/2]、の要素を取りn/2ます。

の場合A[n/2]-A[n/4] = n/2-n/4A[n/2]A[n/4]は同じグループにあります-スキップして、かどうかA[3n/8]を確認してください。A[n/8]A[n/2]-A[n/8] = n/2-n/8

の場合A[n/2]-A[n/4] != n/2-n/4、2つのグループが手元にあります。1つは A[n/2]inを持ち、もう1つはinを持ちます。それがと同じグループにあるかどうかを A[n/4]確認します。それがと同じグループにあるかどうかを確認し、そうでない場合は、のグループにあるかどうかを確認します。 A[n/8]A[n/4]A[3/8]A[n/2]A[n/4]

ソートアルゴリズムと組み合わせることもできますが、それだけの価値はないと思います。これは高速です-対数時間で、モジュール式です。

于 2012-11-27T21:10:52.403 に答える
0
$sorted = $numbers; 
sort($sorted);
$sorted[] = null;  # add a null so the last iteration stores the final range
$ranges = array();
$end = null;
$start = null;

foreach ($sorted as $x) {
    if ($start === null) {
        # first iteration.  New range, but there's no previous one to mention
        $start = $x;
    }
    elseif ($x !== $end + 1) {
        # non-contiguous values == new range.
        # squirrel away the one we were just working on, and start fresh
        $ranges[] = ($start === $end) ? "$start" : "$start-$end";
        $start = $x;
    }
    $end = $x;
}

$ranges_str = implode(', ', $ranges);
于 2012-11-27T22:36:52.977 に答える
0
function get_ranges($numbers) {
sort($numbers);
$ranges=array();
while(current($numbers)){
$start=current($numbers);
$next=next($numbers);
$current=$start;
while( ($next-$current)==1){
    $current=$next;
    $next=next($numbers);
}
$ranges[]=array('start'=>$start,'end'=>$current);
}

return $ranges;

}
于 2017-04-19T23:47:21.403 に答える