2017-10-17 12 views
1

Je fais une webapp de type Excel où les colonnes sont "numérotées" comme a, b, c, ..., aa, ab, ..., az, ba , ..., zz, aaa, .... Mais si j'écrisPHP: comparaison lors du comptage avec des variables de caractères incrémentés

$start = 'a'; 
$end = 'z'; 

while($start <= $end){ 
    echo $start++ . ", "; 
} 

(Avis $ start < = fin $) il ira un jusqu'à yz, pas seulement az parce

echo 'aa' <= 'z'; // true, but 
echo 'za' <= 'z'; // false. 

Est il existe une fonction ou un moyen de comparer deux variables en tenant compte du fait que

$a = "z"; echo ++$a; // aa 
$a = "zz"; echo ++$a; // aaa 

afin que

$a = "z"; $b = $a; $b++; // $b = aa 

AisLessThanB(a,b); // returns true 

et ainsi de suite? Cela signifie que lorsque

a < z < aa < az < zz < aaa < zzz <

AAAA

est toujours vrai ?

EDIT: Quelque chose comme

$start = 'a'; 
$end = 'cv'; // 100 columns 

devrait fonctionner puisque nous travaillons avec des charges de colonnes.

Merci!

+1

pourquoi est 'AA' <' Z' –

Répondre

0

Essayez ceci:

// From https://stackoverflow.com/a/3580935/3088508 
function getLetterIndexInAlphabet ($letter) { 
    return ord($letter) - 96; 
} 

function convertStringToNumber ($inStr) { 
    $letters = array_reverse(str_split($inStr)); 
    $outNum = 0; 
    for ($i = count($letters) - 1; $i >= 0; $i--) { 
     $outNum += getLetterIndexInAlphabet($letters[$i]) * (pow(26, $i)); 
    } 
    return $outNum; 
} 

function AisLessThanB ($a, $b) { 
    $aInt = convertStringToNumber($a); 
    $bInt = convertStringToNumber($b); 
    return ($aInt < $bInt); 
} 

convertStringToNumber est la fonction la plus complexe ici, donc nous allons jeter un oeil à la façon dont il fonctionne sur quelques valeurs:

  • 'c' Equivaut à 2 qui est calculé par:
    1. 'c' = 3 (index alphabétique)
  • 'ba' évalue à 53, qui est calculée par:
    1. 'b' = 52 = (2 (index en alphabet) x (26 (valeur de base)^1 (numéro de colonne))).
    2. 'a' = 1 (indice de l'alphabet)
  • 'bca' évalue à 1431, qui est calculée par:
    1. 'b' = 1352 = (2 (indice en alphabet) x (26 (valeur de base)^2 (numéro de colonne))).
    2. 'c' = 78 = (3 (indice en alphabet) x (26 (valeur de base)^1 (numéro de colonne))).
    3. 'a' = 1 (indice de l'alphabet)
  • 'bdca' évalue à 37.935 qui est calculé par:
    1. 'b' = 35152 = (2 (index en alphabet) x (26 (valeur de base)^3 (numéro de colonne))).
    2. 'd' = 2704 = (4 (indice en alphabet) x (26 (valeur de base)^2 (numéro de colonne))).
    3. 'c' = 78 = (3 (indice en alphabet) x (26 (valeur de base)^1 (numéro de colonne))).
    4. 'a' = 1 (index alphabétique)

Voici quelques cas de test:

echo " a < z = " . ((AisLessThanB( 'a', 'z')) ? 'true' : 'false') . "\n"; 
echo " z < aa = " . ((AisLessThanB( 'z', 'aa')) ? 'true' : 'false') . "\n"; 
echo " aa < az = " . ((AisLessThanB( 'aa', 'az')) ? 'true' : 'false') . "\n"; 
echo " az < zz = " . ((AisLessThanB( 'az', 'zz')) ? 'true' : 'false') . "\n"; 
echo " zz < aaa = " . ((AisLessThanB( 'zz', 'aaa')) ? 'true' : 'false') . "\n"; 
echo " aaa < zzz = " . ((AisLessThanB('aaa', 'zzz')) ? 'true' : 'false') . "\n"; 
echo " zzz < aaaa = " . ((AisLessThanB('zzz', 'aaaa')) ? 'true' : 'false') . "\n"; 
echo "\n===================\n\n"; 
echo " z < a = " . ((AisLessThanB( 'z', 'a')) ? 'true' : 'false') . "\n"; 
echo " aa < z = " . ((AisLessThanB( 'aa', 'z')) ? 'true' : 'false') . "\n"; 
echo " az < aa = " . ((AisLessThanB( 'az', 'aa')) ? 'true' : 'false') . "\n"; 
echo " zz < az = " . ((AisLessThanB( 'zz', 'az')) ? 'true' : 'false') . "\n"; 
echo " aaa < zz = " . ((AisLessThanB('aaa', 'zz')) ? 'true' : 'false') . "\n"; 
echo " zzz < aaa = " . ((AisLessThanB('zzz', 'aaa')) ? 'true' : 'false') . "\n"; 
echo "aaaa < zzz = " . ((AisLessThanB('aaaa', 'zzz')) ? 'true' : 'false') . "\n"; 

Et ils sortie:

a < z = true 
    z < aa = true 
    aa < az = true 
    az < zz = true 
    zz < aaa = true 
aaa < zzz = true 
zzz < aaaa = true 

=================== 

    z < a = false 
    aa < z = false 
    az < aa = false 
    zz < az = false 
aaa < zz = false 
zzz < aaa = false 
aaaa < zzz = false 

eval.in demo

Merci d'avoir posé une question aussi intéressante!

+1

Bonne réponse! Je viens de changer le retour de AisLessThanB à $ aInt - $ bInt pour que je puisse utiliser AisLessThanB ($ a, $ b) vs <0, <= 0 ou == 0. Merci! – alejosky

0

Je ne pense pas que ce soit une bonne idée d'incrémenter la chaîne comme ceci. En fait, en incrément une valeur ASCII d'un caractère. La comparaison des chaînes dans ce cas est dans l'ordre alphabétique (https://stackoverflow.com/a/12888720/5346387) donc je suppose que cela ne fonctionnera pas comme prévu.

Mais pour votre question - je ne pense pas qu'il y aurait une fonction native PHP comme ça. Je suggère de créer une fonction de mappage de la liste linéaire des nombres [0,1,2,3 ... 27,28 ..] à votre code alphabétique [a, b, c..aa, ab ...]. J'espère avoir aidé :)

0

Et si vous comparez la longueur de la chaîne avant de comparer les caractères?

function aIsLessThanB($a, $b) { 

    if(strlen($a) == strlen($b)) { 
    $strlen = strlen($a); 

    for($i = 0; $i < $strlen; $i++) { 

     // pick single character at position $i 
     $charA = substr($a, $i, 1); 
     $charB = substr($b, $i, 1); 

     // convert ASCII to integer and compare 
     if(ord($charA) < ord($charB)) { 
     return true; 
     } elseif(ord($charA) > ord($charB)) { 
     return false; 
     } 
    } 

    } elseif(strlen($a) < strlen($b)) { 
    return true; 
    } else { 
    return false; 
    } 
} 
0

Je ne pense pas qu'il y ait un moyen intégré pour y parvenir, mais j'ai pu venir avec ces 2 méthodes:

$start = 'a'; 
$end = 'z'; 

function sumDecimal($n) 
{ 
    return(ord($n)); 
} 

while($start <= $end) 
{ 
    $startArr = str_split($start); 
    $endArr = str_split($end); 
    $startVal = array_sum(array_map("sumDecimal", str_split($start))); 
    $endVal = array_sum(array_map("sumDecimal", str_split($end))); 
    if($startVal <= $endVal) 
    { 
     echo $start++ . ", "; 
    } 
    else 
    { 
     break; 
    } 
} 

Ceci partagera les chaînes $start et $end en Array puis obtiendra ASCII value de tous ses caractères et le résumera. Tant que la valeur de $start est inférieure ou égale à la valeur de $end, elle va itérer, sinon elle s'arrêtera.DEMO

Attention: il traitera autre chose que a...a ou z...z de manière incorrecte. par exemple. Il évaluera az et za comme identique.

Ou

$start = 'a'; 
$end = 'z'; 

while($start <= $end) 
{ 
    if(strlen($start) <= strlen($end)) 
    { 
     echo $start++ . ", "; 
    } 
    else 
    { 
     break; 
    } 
} 

Cela itérer aussi longtemps que la longueur de $start est inférieure ou égale à $end. DEMO

+0

Merci pour votre commentaire. Votre code s'arrête déjà à la deuxième itération lorsque $ start = 'a'; $ end = 'aa'; sont fixés, et malheureusement nos fichiers n'ont pas moins de ~ 30 colonnes donc cela ne fonctionnera pas pour nous. – alejosky