Hilfe, bekomme geeignete Ausgabe nicht auf die Reihe

LegecyWolf

Fox-Wolf furry
Hallo zusammen, ich bräuchte mal Hilfe von euch, da ich selbst irgendwie nicht mehr weiter weiß.

Die Situation ist wie folgt... ich habe ein Array mit diesem Inhalt (es sind immer Nummern!):
1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 25, 26, 27 [...].
Das geht derzeit weiter bis 400 und wird auch irgendwann erweitert.
Ich spitte dieses Array in einer foreach-Schleife und dabei ist mein Ziel diese Information in diese Darstellung zu bringen:
1-6, 8, 10-14, 25-27, [...].

Mir sind leider die Lösungsansätze und Ideen ausgegangen oder ich denke einfach zu kompliziert... Vielleicht weiß von euch einer einen Rat.


Falls wer wissen möchte wieso dieser Aufwand.. Es geht darum das ich alle Personen einer Serie aufliste. Es gibt X Folgen und ich gebe an welche Person in welcher Folge erscheint. Die aktuelle Ausgabe ist wie oben in der Situationsbeschreibung, aber aus Platz und Übersichtsgründen brauche ich sie in dieser von-bis-Darstellung

Sinn und Zweck ist egal, da ich das für mich mache...

Grüße
~LW~
 
Es gibt versch. Lösungen. Als einfaches Script:
PHP:
$array = array(1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 25, 26, 27);
sort($array);
// Ein Array mit allen Zahlen +1 erstellen
$all = range(reset($array),end($array)+1);

$from = false;
$last = false;
$ranges = array();

//Alle Zaheln durchgehen
foreach($all as $item){
  
    if(!in_array($item, $array)){
        //Die Zahl ist nicht enthalten -> ein Block ist fertig
        if($from !== false) {
            //$from ist gesetzt -> ergo ist ein Block fertig
            $ranges[] = ($from == $last)? $from : "{$from}-{$last}";
            $from = false;
        }
    }else{
        //Zahl ist im Array enthalten
        //Falls $from nicht gesetzt ist, jetzt setzen    
        if(!$from) $from = $item;     
    }
    //Letzte Zahl merken
    $last = $item;
}

print_r($ranges);
Code:
Array
(
    [0] => 1-6
    [1] => 8
    [2] => 10-14
    [3] => 25-27
)
 
Was haltet ihr und vor allem Yaslaw davon:

PHP:
$werte = array(1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 25, 26, 27);
sort($werte);

// dem Array "gruppe" werden die Wertepaare übergeben,
// hier der erste/kleinste Wert aus dem Array "werte"
$gruppe[]['von'] = $werte[0];
$gruppe[0]['bis'] = $werte[0];
// Größten Index im Array "gruppe" festlegen
$idx_gruppe = 0;

// Größten Index im Array "werte" ermitteln
$idx_werte = count($werte) - 1;

// Alle Einträge im Array "werte" durchgehen...
for ($a = 1; $a <= $idx_werte; $a++){
// ...und prüfen ob der letzte bis-Wert um 1 kleiner ist,
// dann als neuen bis-Wert einsetzen.
	if (($werte[$a] - 1) == $gruppe[$idx_gruppe]['bis']){
		$gruppe[$idx_gruppe]['bis'] = $werte[$a];
	} else {
// Wenn nicht ist de Reihenfolge unterbrochen, deshalb
// neuen Eintrag im Array "gruppe"
		$idx_gruppe++;
		$gruppe[]['von'] = $werte[$a];
		$gruppe[$idx_gruppe]['bis'] = $werte[$a];
	}
}

var_dump($gruppe);

Code:
Array (
    [0] => Array ( [von] => 1 [bis] => 6 )
    [1] => Array ( [von] => 8 [bis] => 8 )
    [2] => Array ( [von] => 10 [bis] => 14 )
    [3] => Array ( [von] => 25 [bis] => 27 )
)
 
Zuletzt bearbeitet:
Was haltet ihr und vor allem Yaslaw davon:
Anstelle von meinem Range einfach einen Zähler nehmen. Elegant.
Dann einfach immer den [bis] überschreiben bis der Block fertig ist, auch ein guter Ansatz.

Was mich sehr verwirt beim lesen, sind deine Variablenbezeichnungen. $a für Index, $arr und $array für die Arrays. Alles beginnt mit $a. Ich musste den Code darum etwa 3 mal im Kopf durchgehen bis ich den Durchblick hatte.

Und naja, irgendwie gefällt mir die dauernde Verwendung von $arr[count($arr) - 1] nicht besonders. Ist schwer lesbar.. ggf, diesen Unterarray zuerst auslesen.

...
Und irgendwie habe ich imme rnoch einen Knopf im Kopf. Jedesmal wenn ich dn Code anschaue muss ich ihn von neuem auflösen. (ah, Kommentare fehlen!)
 
So was…

PHP:
$gruppe[]['von'] = $werte[0];
$gruppe[0]['bis'] = $werte[0];

…würde ich so schreiben:

PHP:
$gruppe[] = array(
    'von' => $werte[0],
    'bis' => $werte[0]
);

Das soll jetzt keine Verbesserung sein (ist auch keine :)), aber wo ich es schon zu einer Funktion gemacht habe:

PHP:
function tombe(array $werte)
{
    $werteCount = count($werte);

    if ($werteCount === 0) {
        return array();
    }

    sort($werte);

    $gruppe = array();
    $idx_gruppe = -1;

    $gruppe[] = array(
        'von' => $werte[0],
        'bis' => $werte[0]
    );
    $idx_gruppe++;

    for ($a = 1; $a < $werteCount; $a++) {
        if ($werte[$a] > $gruppe[$idx_gruppe]['bis'] + 1) {
            $gruppe[] = array(
                'von' => $werte[$a],
                'bis' => $werte[$a]
            );
            $idx_gruppe++;
        } else {
            $gruppe[$idx_gruppe]['bis']++;
        }
    }

    return $gruppe;
}
 
Das mit dem Umschreiben in =array() habe ich heute morgen auch gemacht.
Ich habe für mich das nochmals angeschaut und was ausgetestet. Nur hatte ich mein Resultat nicht veröffentlicht. baer so für den Ideenpool:
PHP:
$values = array(1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 25, 26, 27);

//Array mit dem ersten iIntrag initialisieren
$rng[] = array('start' =>  $values[0], 'end' => $values[0]);

for($i=1; $i < count($values); $i++){
    //Index/Key des letzten Eintrages
    $actPairIdx = ucase($rng);
    //prüfen ob der aktuelle Eintrag-1 dem letzten end entspricht. Wenn ja, end überschreiben, ansonsten neuer subarray beginnen
    if($values[$i] - 1 == $rng[$actPairIdx]['end']){
        $rng[$actPairIdx]['end'] = $values[$i];
    }else{
        $rng[] = array('start' =>  $values[$i], 'end' => $values[$i]);
    }
}

print_r($rng);

Verwendete Funktion ucase()
PHP:
/**
 * Gibt den letzen Index/Key eines Arrays zurück
 * Der Befehlsnamen selber habe ich aus VBA übernommen
 * Den Lösungsanatz von http://stackoverflow.com/questions/2348205/how-to-get-last-key-in-an-array
 * @param     Array<item> $iArray
 * @return    Number/String  (Index/Key)
 */
function ucase($iArray){
    end($iArray);         // move the internal pointer to the end of the array
    return key($iArray);    
}
 

Neue Beiträge

Zurück