PHP:使用递增的字符变量进行计数时的比较

问题描述:

我正在做一个类似Excel的web应用程序,其中的列“编号”为a,b,c,...,aa,ab,...,az,ba ,...,zz,aaa,...。但是,如果我写PHP:使用递增的字符变量进行计数时的比较

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

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

(通知$开始< = $结束),它会去一个高达YZ,不只是AZ因为

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

是有一个函数或一种方法来比较两个变量,记住:

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

使

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

AisLessThanB(a,b); // returns true 

等等?这意味着其中

一个<ž< AA < AZ < ZZ < AAA < ZZZ < AAAA

总是

编辑:喜欢的东西

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

应该工作,因为我们同列负荷工作。

谢谢!

+1

为什么'AA'

试试这个:

// From https://*.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是这里最复杂的功能,让我们来看看它是如何工作的几个值:

  • 'c'计算结果为2,它是计算结果:
    1. 'c' = 3(字母索引)
  • 'ba'计算结果为,其由下式计算53:
    1. 'b' = 52 =(2(指数在字母)×(26(基值)^ 1(列数)))。
    2. 'a' = 1(在字母索引)
  • 'bca'计算为1431,其由下式计算:
    1. 'b' = 1352 =(2(指数在字母)×(26(基值)^ 2(列号)))。
    2. 'c' = 78 =(3(字母索引)×(26(基值)^ 1(列号)))。
    3. 'a' = 1(在字母索引)
  • 'bdca'计算为37935,其由下式计算:
    1. 'b' = 35152 =(2(指数在字母)×(26(基值)^ 3(列号)))。
    2. 'd' = 2704 =(4(字母索引)×(26(基准值)^ 2(列号)))。
    3. 'c' = 78 =(3(字母索引)×(26(基值)^ 1(列号)))。
    4. 'a' = 1(在字母索引)

这里的一些测试情况:

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"; 

他们输出:

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

感谢您提出这样一个有趣的问题!

+1

很好的回答!我只是将AisLessThanB的返回值更改为$ aInt - $ bInt,所以我可以使用AisLessThanB($ a,$ b)vs alejosky

我不认为这样增加字符串是个好主意。实际上,增加一个char的ASCII值。在这种情况下字符串的比较是按字母顺序排列的(https://*.com/a/12888720/5346387),所以我猜它不会按照您的预期工作。

但是对于你的问题 - 我不认为会有这样的PHP本地函数。我建议创建一个从数字[0,1,2,3 ... 27,28 ..]的线性列表到您的字母代码[a,b,c..aa,ab ...]的映射函数。我希望我帮助:)

如果比较字符之前比较字符串长度怎么办?

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; 
    } 
} 

我不认为有一个内置的方式来实现这一点,但我能想出这2种方法:

$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; 
    } 
} 

这将分裂$start$end串到Array,然后将得到其所有字符ASCII value,并将其总结。只要$start的值小于或等于$end的值,它将迭代,否则它将停止。DEMO

当心:将治疗以外的任何其他a...az...z不正确。例如它将评估azza相同。

或者

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

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

这将只要$start的长度小于或等于$end迭代。 DEMO

+0

感谢您的评论。您的代码已经在第二次迭代中停止,当时$ start ='a'; $ end ='aa';我们的文件不得少于30列,所以这对我们来说不起作用。 – alejosky