
In PHP esiste la funzione range() che serve a creare un array di elementi a partire da un singolo range di numeri specificato.
Il problema è che in PHP non esiste la funzione contraria, ovvero che da un array di numeri restituisca, in una qualunque forma, la sua rappresentazione compatta. Nel caso specifico di range() la rappresentazione compatta in input consta solo dei due numeri che rappresentano gli estremi del range.
Grazie alla collaborazione di Fabrizio Catalucci (concept) e Fabio Ambrosanio (debugging) sono lieto di pubblicare questa piccola funzione range_compact() che colma proprio questa mancanza delle librerie standard di PHP.
La funzione range_compact() si avvale della funzione speciale common_prefix() per trovare la parte comune di due stringhe.
/**
* Restituisce la parte comune di due stringhe partendo da sinistra
* @param string $s1 - Prima stringa
* @param string $s2 - Seconda stringa
* @return string Stringa comune alle due iniziando il confronto da sinistra
* @example common_prefix("abc", "ab") = "ab"
*/
function common_prefix($s1, $s2)
{
$s1 = strval($s1);
$s2 = strval($s2);
$n = min(strlen($s1), strlen($s2));
$i = 0;
while ($i < $n && $s1{$i} === $s2{$i}) {
$i++;
}
return substr($s1, 0, $i);
}
/**
* Rappresenta un array ordinato di interi in insiemi.
*
* Gli insiemi sono restituiti sotto forma di stringa con formato interpretato compatto,
* di comoda comprensione per gli essere umani
*
* @param array $v - Array di interi da raggruppare (anche in formato stringa), già ordinato in ordine crescente
* @param int $offset - Numero di cifre da ignorare a partire dall'inizio dell'array
* @param int $step - Dimensione del passo con cui raggruppare
* @param bool $compress - Opzione per rappresentare gli insiemi contigui con notazione compressa a seconda delle cifre diverse tra il primo e l'ultimo elemento di ogni insieme
* @param int $trunc_left - Rimuove le prime N cifre da sinistra nella rappresentazione finale, per entrambi gli estremi di ogni insieme
* @param string $seq_sep - Separatore di insiemi non contigui
* @param string $range_sep - Separatore di insiemi contigui
* @return string Stringa rappresentante il raggruppamento per insiemi
*
* @example $a = array(3, 4, 7, 8, 9, 10, 12);
* print_r(range_compact($a));
* OUTPUT: 3-4, 7-10, 12
* @example $a = array(30, 40, 70, 80, 90, 100, 120);
* print_r(range_compact($a, 0, 10));
* OUTPUT: 30-40, 70-100, 120
* @example $a = array(3906123456780, 3906123456781, 3906123456782, 3906123456785, 3906123456790, 3906123456791, 3906123456792, 3906123456793, 3906123456794, 3906123456795, 3906123456796, 3906123456797, 3906123456798, 3906123456799, 3906123456800);
* print_r(range_compact($a, 0, 1, true, 2));
* OUTPUT: 06123456780-2, 06123456785, 06123456790-800
* print_r(range_compact($a, 0, 1, false, 2));
* OUTPUT: 06123456780-06123456782, 06123456785, 06123456790-06123456800
* print_r(range_compact($a, 0, 1));
* OUTPUT: 3906123456780-3906123456782, 3906123456785, 3906123456790-3906123456800
*/
function range_compact($v, $offset = 0, $step = 1, $compress = false, $trunc_left = 0, $seq_sep = ", ", $range_sep = "-")
{
$lun = count($v) + 1;
$firstseq = $offset;
$lastseq = $firstseq;
for($i = $offset + 1; $i < $lun; $i++) {
if($v[$i - 1] == $v[$i] - $step) {
$lastseq = $i;
} else {
$sysc = $sysc . substr($v[$firstseq], $trunc_left);
if($lastseq > $firstseq) {
if($compress == false) {
$sysc = $sysc . $range_sep . substr($v[$lastseq], $trunc_left);
} else {
$lastelem = substr($v[$lastseq], strlen(common_prefix($v[$firstseq],$v[$lastseq])));
$sysc = $sysc . $range_sep . $lastelem;
}
}
if($i < $lun - 1) {
$sysc = $sysc . $seq_sep;
}
$firstseq = $i;
$lastseq = $firstseq;
}
}
if($lastseq > $firstseq) {
return $sysc . substr($v[$firstseq], $trunc_left) . $range_sep . substr($v[$lun], $trunc_left);
} else {
return $sysc . substr($v[$lun], $trunc_left);
}
}
Condividi:
- Fai clic per condividere su Telegram (Si apre in una nuova finestra)
- Fai clic per condividere su WhatsApp (Si apre in una nuova finestra)
- Fai clic per condividere su Facebook (Si apre in una nuova finestra)
- Fai clic qui per condividere su Twitter (Si apre in una nuova finestra)
- Fai clic qui per condividere su LinkedIn (Si apre in una nuova finestra)
- Fai clic qui per condividere su Pinterest (Si apre in una nuova finestra)
- Fai clic qui per condividere su Reddit (Si apre in una nuova finestra)
- Fai clic qui per condividere su Tumblr (Si apre in una nuova finestra)
- Fai clic qui per condividere su Pocket (Si apre in una nuova finestra)
- Fai clic per inviare un link a un amico via e-mail (Si apre in una nuova finestra)
- Fai clic qui per stampare (Si apre in una nuova finestra)