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

时间:2017-10-17 10:14:06

标签: php comparison

我正在做类似Excel的webapp,其中列被“编号”,如 a,b,c,...,aa,ab,...,az,ba,...,zz, AAA,... 的。但如果我写

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

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

(注意 $ start &lt; = $ end )它将 a 一直到 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

等等?这意味着

  

a&lt; z&lt; aa&lt; az&lt; zz&lt; aaa&lt; zzz&lt; AAAA

始终是 true

编辑:类似

的内容
$start = 'a';
$end = 'cv'; // 100 columns

应该可以工作,因为我们处理大量的列。

谢谢!

4 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

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 :(得分:0)

我不认为有一种内置的方法来实现这一目标,但我能够提出这两种方法:

$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

答案 3 :(得分:0)

试试这个:

// 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是这里最复杂的功能,所以让我们看一下它在几个值上是如何工作的:

  • 'c'评估为2,其计算公式为:
    1. 'c' = 3(字母索引)
  • 'ba'评估为53,其计算公式为:
    1. 'b' = 52 =(2(字母表中的索引)x(26(基值)^ 1(列号)))。
    2. 'a' = 1(字母表中的索引)
  • 'bca'评估为1431,计算方法如下:
    1. 'b' = 1352 =(2(字母表中的索引)x(26(基值)^ 2(列号)))。
    2. 'c' = 78 =(3(字母表中的索引)x(26(基值)^ 1(列号)))。
    3. 'a' = 1(字母表中的索引)
  • 'bdca'评估为37935,计算方法如下:
    1. 'b' = 35152 =(2(字母表中的索引)x(26(基值)^ 3(列号)))。
    2. 'd' = 2704 =(4(字母表中的索引)x(26(基值)^ 2(列号)))。
    3. 'c' = 78 =(3(字母表中的索引)x(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

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