3

英数字のインクリメンターを使用してシーケンス(または「次のID」を取得する関数)を生成する必要があります。

文字列の長さは定義可能である必要があり、文字は0〜9、AZである必要があります。

たとえば、長さが3の場合。

000
001
002
~
009
00A
00B
~
00Z
010
011
etc..

したがって、この関数は次のように使用される可能性があると思います。

$code = '009'
$code = getNextAlphaNumeric($code);
ehco $code; // '00A'

私はこれに対する解決策に自分で取り組んでいますが、誰かが以前にこれに取り組み、私自身よりも賢く/より堅牢な解決策を思いついたのかどうか興味があります。

誰かがこの問題に対する素晴らしい解決策を持っていますか?

4

5 に答える 5

9

base_convertのようなものは機能しますか?たぶんこれらの線に沿って(未テスト)

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

コードはすべて実際には基数36の数値であるため、その基数36の数値を基数10に変換し、それに1を加算してから、基数36に変換して返します。

編集:コードには任意の文字列長がある可能性があることに気づきましたが、このアプローチはまだ実行可能である可能性があります-最初にすべての先行ゼロをキャプチャしてからそれらを取り除き、ベース36->ベース10変換を実行し、追加します1つ、必要な先行ゼロを追加し直します..。

于 2012-08-17T06:54:24.823 に答える
1
<?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
?>
于 2012-08-17T07:42:28.033 に答える
1

私はこのようなことをします:

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;
}
于 2012-08-17T07:03:18.440 に答える
1

私はこの問題のより一般的な解決策、つまり任意の文字セットを任意の順序で処理することに興味がありました。最初にアルファベットのインデックスに翻訳してから、もう一度戻すのが最も簡単だと思いました。

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";
于 2012-08-17T07:36:18.820 に答える
0
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);

}

于 2014-12-19T10:32:48.363 に答える