繁体   English   中英

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

[英]What is the most efficient way to move through a PHP array a number of times in one direction or another?

简单示例:以英文 abecedary(范围 AZ)为参考。 如果给了我一封信——比如说“a”——还有一个数字——比如说“2”——我需要找出字母 2 之后的位置是什么。 答案是 'c' ('a'--> 1 move:'b' --> 2 move:'c')

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

该问题的最后一种情况是您可能会收到一个负数。 因此,如果为字母 'a' 提供数字 '-3',则答案将是 'x' ('a'--> 1 move:'z' --> 2 move:'y' --> 3 move: '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 以“修复”它。

演示

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

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

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


所以,代码很简单。

  • 对数字应用模 26。
  • 获取当前字符的 ascii 值并为其添加“数字”。
  • 如果新的 ascii 值在 65 到 90 的范围内,则返回 char 值。
  • 如果新的 ascii 值超过 90,则消耗偏移量直到 90 并返回它的 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);
}

演示: 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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM