在一个方向或另一个方向多次移动 PHP 数组的最有效方法是什么?
What is the most efficient way to move through a PHP array a number of times in one direction or another?
简单的例子:
以英语基础(范围 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
我的函数有两个主要问题:
- 即使我让它与正数一起工作,编译器return 也需要时间来回答,所以恐怕这是一个非常耗时的操作,可以更容易地解决。
- 我的函数方法不适用于负数。我非常清楚什么是未定义的偏移量,它无法访问我的数组的负索引。我只是不知道如何使模运算符向后工作...
任何帮助解决这个问题的人都将由衷地感谢你。
取模 26 是一个正确的想法。
这是因为,1
的偏移量与 27
的偏移量相同。 0
的偏移量与偏移量 26
、52
等相同,依此类推。
对负数取模 26 也应用相同的逻辑,因为 -27
的旋转与 -1
的旋转相同。
所以,代码很简单。
- 对数字应用模 26。
- 获取当前字符的 ascii 值并向其添加“数字”。
- 如果新的 ascii 值在 65 和 90 之间,return char 值。
- 如果新的 ascii 值超过 90,则使用偏移量直到 90 和 return 它的 chr() + 64。如果值低于 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);
}
下面应该这样做:
function getNewLetter(string $letter, int $number): string
{
$newOrd = (ord($letter) + $number - 65) % 26;
if ($newOrd < 0) {
$newOrd += 26;
}
return chr(65 + $newOrd);
}
它只是对新字母相对于字母 A (65) 的序数值使用模 26。如果它小于 0,它会再次添加 26 以“修复”它。
Jeto 的方法改进为 return 大写或小写字母的正确答案:
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;
简单的例子: 以英语基础(范围 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
我的函数有两个主要问题:
- 即使我让它与正数一起工作,编译器return 也需要时间来回答,所以恐怕这是一个非常耗时的操作,可以更容易地解决。
- 我的函数方法不适用于负数。我非常清楚什么是未定义的偏移量,它无法访问我的数组的负索引。我只是不知道如何使模运算符向后工作...
任何帮助解决这个问题的人都将由衷地感谢你。
取模 26 是一个正确的想法。
这是因为,1
的偏移量与 27
的偏移量相同。 0
的偏移量与偏移量 26
、52
等相同,依此类推。
对负数取模 26 也应用相同的逻辑,因为 -27
的旋转与 -1
的旋转相同。
所以,代码很简单。
- 对数字应用模 26。
- 获取当前字符的 ascii 值并向其添加“数字”。
- 如果新的 ascii 值在 65 和 90 之间,return char 值。
- 如果新的 ascii 值超过 90,则使用偏移量直到 90 和 return 它的 chr() + 64。如果值低于 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);
}
下面应该这样做:
function getNewLetter(string $letter, int $number): string
{
$newOrd = (ord($letter) + $number - 65) % 26;
if ($newOrd < 0) {
$newOrd += 26;
}
return chr(65 + $newOrd);
}
它只是对新字母相对于字母 A (65) 的序数值使用模 26。如果它小于 0,它会再次添加 26 以“修复”它。
Jeto 的方法改进为 return 大写或小写字母的正确答案:
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;