在PHP数组中向一个或另一个方向多次移动的最有效方法是什么



简单示例:以英语初级读本(范围a-Z(为参考。如果给我一个字母(比如说"a"(和一个数字(比如"2"(,我需要找出字母2的位置。答案是"c"("a"-->1步:"b"-->2步:"c"(

当然,你可以得到一个比初始字母大的数字,即26。由于规则是在字母z之后又是字母a,这意味着如果在前面的例子中传递了数字26,我们需要找到的字母将是"a"。

问题的最后一种情况是,您可能会收到一个负数。因此,如果字母"a"的数字为"-3",则答案为"x"("a"-->1次移动:"z"-->2次移动:‘y’-->3次移动:'x'(。

这是我迄今为止的代码:

function getNewLetter($letter, $number) {
$letters = range('A', 'Z');
if ($number >= 0) {
return $letters[($number + array_search($letter, $letters) % 26)%26];
} else {
return $letters[($number - (array_search($letter, $letters) % 26))%26];
}
}
echo getNewLetter("H", 4);      // correctly prints out L
echo getNewLetter("H", 26);       // correctly prints out H
echo getNewLetter("H", -4);     // throws undefined offset -11 error

我的功能有两个主要问题:

  • 即使我使用正数,编译器返回答案也需要时间,所以我担心这是一个非常耗时的操作,可以更容易地进行排序
  • 我的函数方法不适用于负数。我非常清楚什么是未定义的偏移量,它不能访问我的数组的负索引。我只是不知道如何使模运算符反向工作

对于如何解决这一问题的任何帮助,我都将衷心感谢。

以下操作应该完成:

function getNewLetter(string $letter, int $number): string
{
$newOrd = (ord($letter) + $number - 65) % 26;
if ($newOrd < 0) {
$newOrd += 26;
}
return chr(65 + $newOrd);
}

它只是对新字母的序数值使用模26,相对于字母a(65(的序数值。如果是<0时,它再次将26加到"0"上;"修复";它回来了。

演示

取模26是一个正确的想法。

这是因为1的偏移量与27的偏移量相同。0的偏移量与2652等的偏移量相同,依此类推。

取负数的模26也应用与-27的旋转与-1的旋转相同的逻辑。


因此,代码很简单。

  • 对数字应用模26
  • 取当前字符的ascii值;数字";对它
  • 如果新的ascii值在65到90之间,则返回char值
  • 如果新的ascii值超过90,则使用偏移量直到90,并返回其+64的chr((。如果值低于65,则同样适用,反之亦然

代码段:

function getNewLetter($letter, $number) {
$number = $number % 26;
$new_ascii_value = ord($letter) + $number;
if($new_ascii_value < 65){
$number = abs($number) - (ord($letter) - 65);
return chr(91 - $number);
}else if($new_ascii_value >= 91){
return chr(64 + ($new_ascii_value - 90));
}
return chr($new_ascii_value);
}

演示:https://3v4l.org/0Yhkm

Jeto的方法经过改进,可以用大写或小写字母返回正确答案:

function getNewLetter(string $letter, int $number): string {
$movement = $letter < 'a' ? 65 : 97;      // Depending on case, letter 'a' starts at different numbers of ASCII table
$newOrd = (ord($letter) + $number - $movement) % 26;
if ($newOrd < 0) {
$newOrd += 26;
}
return chr($movement + $newOrd);
}

这里有一些通过测试的方法:

echo getNewLetter("h", 4), PHP_EOL;
echo getNewLetter("H", 4), PHP_EOL;
echo getNewLetter("h", -4), PHP_EOL;
echo getNewLetter("H", -4), PHP_EOL;
echo getNewLetter("h", 26), PHP_EOL;
echo getNewLetter("H", 26), PHP_EOL;
echo getNewLetter("H", 27), PHP_EOL;
echo getNewLetter("H", -26), PHP_EOL;
echo getNewLetter("H", -27), PHP_EOL;
echo PHP_EOL;
echo getNewLetter("a", -2), PHP_EOL;
echo getNewLetter("A", -2), PHP_EOL;
echo getNewLetter("b", -3), PHP_EOL;
echo getNewLetter("B", -3), PHP_EOL;
echo PHP_EOL;
echo getNewLetter("Z", 2), PHP_EOL;
echo getNewLetter("Z", 26), PHP_EOL;
echo getNewLetter("Z", 27), PHP_EOL;
echo getNewLetter("Z", -26), PHP_EOL;
echo getNewLetter("Z", -27), PHP_EOL;
echo PHP_EOL;
echo getNewLetter("A", -1), PHP_EOL;
echo getNewLetter("A", -27), PHP_EOL;

最新更新