Alphanumeric Increment a string in PHP (To a certain length)

前端 未结 5 1942
鱼传尺愫
鱼传尺愫 2020-12-21 05:50

I need to generate a sequence (or function to get a \"next id\") with an alphanumeric incrementor.

The length of the string must be defineable, and the Characters mu

相关标签:
5条回答
  • 2020-12-21 06:07

    Would something like base_convert work? Maybe along these lines (untested)

    function getNextAlphaNumeric($code) {
       $base_ten = base_convert($code,36,10);
       return base_convert($base_ten+1,10,36);
    }
    

    The idea is that your codes are all really just a base 36 number, so you convert that base 36 number to base 10, add 1 to it, then convert it back to base 36 and return it.

    EDIT: Just realized that there may be an arbitrary string length of the code, but this approach might still be doable -- if you capture all the leading zeroes first, then strip them off, do the base 36 -> base 10 conversion, add one, and add back any needed leading zeroes ...

    0 讨论(0)
  • 2020-12-21 06:07
    <?php
    define('ALPHA_ID_LENGTH', 3);
    
    class AlphaNumericIdIncrementor {
     // current id
     protected $_id;
    
     /**
      * check if id is valid
      *
      * @param  string  $id
      * @return bool
      **/
     protected static function _isValidId($id) {
      if(strlen($id) > ALPHA_ID_LENGTH) {
       return false;
      }
    
      if(!is_numeric(base_convert($id, 36, 10))) {
       return false;
      }
    
      return true;
     }
    
     /**
      * format $id
      * fill with leading zeros and transform to uppercase
      *
      * @param  string  $id
      * @return string
      **/
     protected static function _formatId($id) {
      // fill with leading zeros
      if(strlen($id) < ALPHA_ID_LENGTH) {
       $zeros = '';
    
       for($i = 0; $i < ALPHA_ID_LENGTH - strlen($id); $i++) {
        $zeros .= '0';
       }
    
       $id = strtoupper($zeros . $id);
      } else {
       $id = strtoupper($id);
      }
    
      return $id;
     }
    
     /**
      * construct
      * set start id or null, if start with zero
      *
      * @param  string  $startId
      * @return void
      * @throws Exception
      **/
     public function __construct($startId = null) {
      if(!is_null($startId)) {
       if(self::_isValidId($startId)) {
        $this->_id = $startId;
       } else {
        throw new Exception('invalid id');
       }
      } else {
       $this->_generateId();
      }
     }
    
     /**
      * generate start id if start id is empty
      *
      * @return void
      **/
     protected function _generateId() {
      $this->_id = self::_formatId(base_convert(0, 10, 36));
     }
    
     /**
      * return the current id
      *
      * @return string
      **/
     public function getId() {
      return $this->_id;
     }
    
     /**
      * get next free id and increment $this->_id
      *
      * @return string
      **/
     public function getNextId() {
      $this->_id = self::_formatId(base_convert(base_convert($this->_id, 36, 10) + 1, 10, 36));
    
      return $this->_id;
     }
    }
    
    $testId = new AlphaNumericIdIncrementor();
    echo($testId->getId() . '<br />'); // 000
    echo($testId->getNextId() . '<br />'); // 001
    
    $testId2 = new AlphaNumericIdIncrementor('A03');
    echo($testId2->getId() . '<br />'); // A03
    echo($testId2->getNextId() . '<br />'); // A04
    
    $testId3 = new AlphaNumericIdIncrementor('ABZ');
    echo($testId3->getId() . '<br />'); // ABZ
    echo($testId3->getNextId() . '<br />'); // AC0
    ?>
    
    0 讨论(0)
  • 2020-12-21 06:10

    I was interested in the more general solution to this problem - i.e. dealing with arbitrary character sets in arbitrary orders. I found it easiest to first translate to alphabet indexes and back again.

    function getNextAlphaNumeric($code, $alphabet) {
    
      // convert to indexes
      $n = strlen($code);
      $trans = array();
      for ($i = 0; $i < $n; $i++) {
         $trans[$i] = array_search($code[$i], $alphabet);
      }
    
      // add 1 to rightmost pos
      $trans[$n - 1]++;
    
      // carry from right to left
      $alphasize = count($alphabet);
      for ($i = $n - 1; $i >= 0; $i--) {
         if ($trans[$i] >= $alphasize) {
           $trans[$i] = 0;
           if ($i > 0) {
             $trans[$i -1]++;
           } else {
             // overflow
           }
         }
      }
    
      // convert back
      $out = str_repeat(' ', $n);
      for ($i = 0; $i < $n; $i++) {
         $out[$i] = $alphabet[$trans[$i]];
      }
    
      return $out;
    }
    
    $alphabet = array();
    for ($i = ord('0'); $i <= ord('9'); $i++) {
      $alphabet[] = chr($i);
    }
    for ($i = ord('A'); $i <= ord('Z'); $i++) {
      $alphabet[] = chr($i);
    }
    
    echo getNextAlphaNumeric('009', $alphabet) . "\n";
    echo getNextAlphaNumeric('00Z', $alphabet) . "\n";
    echo getNextAlphaNumeric('0ZZ', $alphabet) . "\n";
    
    0 讨论(0)
  • 2020-12-21 06:11
    function formatPackageNumber($input)
     { 
      //$input = $_GET['number'];
    
      $alpha_array = array("A", "B" , "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
      $number_array = array("0", "1" , "2", "3", "4", "5", "6", "7", "8", "9");
      $output = "";
    
      for($i=0; $i<=5; $i++){
         if($i>=4) {
          $divisor = pow(26,$i-3)*pow(10,3);
        } else {
          $divisor = pow(10,$i);
        }
        $pos = floor($input/$divisor);
    
        if($i>=3) {
          $digit = $pos%26;
          $output .= $alpha_array[$digit];
        } else {
          $digit = $pos%10 ;
          $output .= $number_array[$digit];
        }
      } 
    return  strrev($output);
    

    }

    0 讨论(0)
  • I would do something like this:

    getNextChar($character) {
        if ($character == '9') {
            return 'A';
        }
        else if ($character == 'Z') {
            return '0';
        }
        else {
            return chr( ord($character) + 1);
        }
    }
    
    getNextCode($code) {
        // reverse, make into array
        $codeRevArr = str_split(strrev($code));
    
        foreach($codeRevArr as &$character) {
            $character = getNextChar($character);
            // keep going down the line if we're moving from 'Z' to '0'
            if ($character != '0') {
                break;
            }
        }
    
        // array to string, then reverse again
        $newCode = strrev(implode('', $codeRevArr));
        return $newCode;
    }
    
    0 讨论(0)
提交回复
热议问题