我想编写一个接受3个字符并将其递增的函数,并将新递增的字符作为字符串返回。
我知道如何将单个字母增加到下一个字母,但是我怎么知道何时增加第二个字母,然后停止然后再增加第一个字母以实现顺序增加?
So if AAA is passed, return AAB. If
AAZ is passed return ABA (hard part).
我希望您能提供有关逻辑的帮助以及使用哪些PHP函数的帮助。
更好的是,是否已经完成了此操作,或者有可用的类来执行此操作?
谢谢大家的帮助
我不明白。 AAA => AAB,但AAZ => ABA。 您如何确定要递增的字母? 您说增加第二个字母,所以我认为您是指除第一个字母以外的所有字母? 如果您将除第一个字母以外的所有字母加一,是否应该是AAA => ABB?
@Raoul Duke:以26为基数,没有数字,只有字母。
@Matt啊,好吧。 谢谢
@Raoul-只需运行$ X = AAA; for($ i = 1; $ i <1024; $ i ++){echo $ X ++,
; }看看是什么意思。
字符/字符串递增在PHP中有效(尽管不能递减)
$x = 'AAZ';
$x++;
echo $x;
遗憾的是$ x--无法正常工作。 @wimvds-感谢您添加链接
或者只是echo ++$x; :)
正如文档所述,decementing应该与$ a--一起使用:php.net/manual/en/language.operators.increment.php
@TobiasGaertner-递减数字适用于$a--;减少字符/字母不会...示例...并且您链接的文档页面专门显示Note that character variables can be incremented but not decremented
@Mark Ba??ker-是的,您是对的-我的错误-只是写得不够仔细。抱歉
您可以使用++运算符。
$i = 'aaz';
$i++;
print $i;
aba
但是,此实现有一些奇怪的事情:
for($i = 'a'; $i < 'z'; $i++) print"$i";
这将打印出从a到y的字母。
for($i = 'a'; $i <= 'z'; $i++) print"$i";
这将打印出从a到z的字母,并以aa继续,以yz结尾。
它并不奇怪,只是不直观。如果$i == z条件仍然成立,并且for循环将继续,将$i设置为aa。仅当$i达到za时,条件才变为假。
如PHP RFC中所建议:严格运算符指令
(目前正在讨论中):
Using the increment function on a string will throw a TypeError when strict_operators is enabled.
无论RFC是否合并,PHP迟早都会朝着增加操作员严格性的方向发展。因此,不应增加字符串。
a-z / A-Z范围
如果您知道字母将保持在a-z / A-Z范围内(不超过z / Z),则可以使用将字母转换为ASCII代码,对其进行递增并转换回字母的解决方案。
使用ord()和chr():
$letter = 'A';
$letterAscii = ord($letter);
$letterAscii++;
$letter = chr($letterAscii); // 'B'
ord()将字母转换为ASCII num表示形式
num表示递增
使用chr()将数字转换回字母
正如评论中发现的那样,要小心。这将对ASCII表进行迭代,因此从z(ASCII 90)开始,它不会进入aa,而是进入[(ASCII 91)。
超越z / Z
如果您敢于进一步并且希望z成为aa,这就是我想出的:
final class NextLetter
{
private const ASCII_UPPER_CASE_BOUNDARIES = [65, 91];
private const ASCII_LOWER_CASE_BOUNDARIES = [97, 123];
public static function get(string $previous) : string
{
$letters = str_split($previous);
$output = '';
$increase = true;
while (! empty($letters)) {
$letter = array_pop($letters);
if ($increase) {
$letterAscii = ord($letter);
$letterAscii++;
if ($letterAscii === self::ASCII_UPPER_CASE_BOUNDARIES[1]) {
$letterAscii = self::ASCII_UPPER_CASE_BOUNDARIES[0];
$increase = true;
} elseif ($letterAscii === self::ASCII_LOWER_CASE_BOUNDARIES[1]) {
$letterAscii = self::ASCII_LOWER_CASE_BOUNDARIES[0];
$increase = true;
} else {
$increase = false;
}
$letter = chr($letterAscii);
if ($increase && empty($letters)) {
$letter .= $letter;
}
}
$output = $letter . $output;
}
return $output;
}
}
如果您打算进一步使用它,我也会给您100%的覆盖率。它针对原始字符串增量++进行测试:
/**
* @dataProvider letterProvider
*/
public function testIncrementLetter(string $givenLetter) : void
{
$expectedValue = $givenLetter;
self::assertSame(++$expectedValue, NextLetter::get($givenLetter));
}
/**
* @return iterable
*/
public function letterProvider() : iterable
{
yield ['A'];
yield ['a'];
yield ['z'];
yield ['Z'];
yield ['aaz'];
yield ['aaZ'];
yield ['abz'];
yield ['abZ'];
}
香港专业教育学院尝试过,但它不是从z到aa,而是到{,不是什么奇怪的字符。
嗯,好点,我从来没有走过这么远。我已经编辑了答案。提供反馈对其他人也有帮助,谢谢;)我将尝试编写有效的解决方案而不增加字符串并将其发布在此处。
@ArendE Ive进一步更新了答案
哇,超越! ??
要在7位128字符ASCII范围内递增或递减,最安全的方法是:
$CHAR ="l";
echo chr(ord($CHAR)+1)."".chr(ord($CHAR)-1);
/* m k */
因此,通过递减a作为ascii规范列表来反击是很正常的
打印整个ASCII范围:
for ($i = 0;$i < 127;$i++){
echo chr($i);
}
/* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ */
有关ANSI 7位ASCII的更多信息:man ascii
在8位中增加或减少256个字符的UTF-8范围。
这在主机字符集方面开始有所不同。但是这些字符集都可以在现代机器上使用。在php中,最安全的方法是使用php-mbstring扩展名:https://www.php.net/manual/zh/function.mb-chr.php
Extended ASCII (EASCII or high ASCII) character encodings are
eight-bit or larger encodings that include the standard seven-bit
ASCII characters, plus additional characters. https://en.wikipedia.org/wiki/Extended_ASCII
例如,更多信息:man iso_8859-9
ISO 8859-1 West European languages (Latin-1)
ISO 8859-2 Central and East European languages (Latin-2)
ISO 8859-3 Southeast European and miscellaneous languages (Latin-3)
ISO 8859-4 Scandinavian/Baltic languages (Latin-4)
ISO 8859-5 Latin/Cyrillic
ISO 8859-6 Latin/Arabic
ISO 8859-7 Latin/Greek
ISO 8859-8 Latin/Hebrew
ISO 8859-9 Latin-1 modification for Turkish (Latin-5)
ISO 8859-10 Lappish/Nordic/Eskimo languages (Latin-6)
ISO 8859-11 Latin/Thai
ISO 8859-13 Baltic Rim languages (Latin-7)
ISO 8859-14 Celtic (Latin-8)
ISO 8859-15 West European languages (Latin-9)
ISO 8859-16 Romanian (Latin-10)
例如,我们可以在ISO 8859-7中找到€符号:
244 164 A4 € EURO SIGN
要在16位UTF-16 Unicode范围内递增或递减:
这是一种通过生成html实体并将其转换为utf8来生成整个unicode字符集的方法。在线运行
for ($x = 0; $x < 262144; $x++){
echo html_entity_decode("".$x.";",ENT_NOQUOTES,"UTF-8");
}
相同的东西,但范围高达(16^4 * 4)!
echo html_entity_decode('',ENT_NOQUOTES,'UTF-8');
/* ! */
echo html_entity_decode('',ENT_NOQUOTES,'UTF-8');
/*" */
要检索Unicode €符号,请使用该字符的base10小数表示。
echo html_entity_decode('€',ENT_NOQUOTES,'UTF-8');
/* € */
使用base16十六进制表示形式的相同符号:
echo html_entity_decode(''.hexdec("20AC").';',ENT_NOQUOTES,'UTF-8');
/* € */
前32位保留用于特殊控制字符,输出垃圾?????,但有含义。
您正在查看数字表示法问题。这是base24(或您的字母有多少个数字)。让我们称之为基数b。
为字母中的每个字母分配一个数字(A = 1,B = 2,C = 3)。
接下来,找出您的输入"数字":表示形式" ABC"表示A*b^2 + B*b^1 + C*b^0
使用此公式可以找到数字(int)。增加它。
接下来,将其转换回数字系统:用b^2除以得到第三位数,第二位数用b^1除以余数(模),最后一位用`b ^ 0 ^除以余数。
这可能会有所帮助:如何从base10转换为任何其他基准。
对。我永远无法真正记住字母表中有多少个字母。这也取决于您的计算方式(有些人忽略了" j"和" v"只是给我的一封不真实的信...
$values[] = 'B';
$values[] = 'A';
$values[] = 'Z';
foreach($values as $value ){
if($value == 'Z'){
$value = '-1';
}
$op = ++$value;
echo $op;
}
?>
至少有一点解释必将对OP和您的答案提供进一步的帮助
您可以将ASCII码用于字母数字。从那里您递增和递减以获得上一个/下一个字符。
您可以将字符串拆分为单个字符,然后将转换应用于这些字符。
只是一些想法可以帮助您入门。
我在c#中有这些方法,您可能可以将其转换为php并进行修改以满足您的需求,但是我不确定Hexavigesimal是这些的确切名称...
#region Hexavigesimal (Excel Column Name to Number)public static int FromHexavigesimal(this string s)
{
int i = 0;
s = s.Reverse();
for (int p = s.Length - 1; p >= 0; p--)
{
char c = s[p];
i += c.toInt() * (int)Math.Pow(26, p);
}
return i;
}
public static string ToHexavigesimal(this int i)
{
StringBuilder s = new StringBuilder();
while (i > 26)
{
int r = i % 26;
if (r == 0)
{
i -= 26;
s.Insert(0, 'Z');
}
else
{
s.Insert(0, r.toChar());
}
i = i / 26;
}
return s.Insert(0, i.toChar()).ToString();
}
public static string Increment(this string s, int offset)
{
return (s.FromHexavigesimal() + offset).ToHexavigesimal();
}
private static char toChar(this int i)
{
return (char)(i + 64);
}
private static int toInt(this char c)
{
return (int)c - 64;
}
#endregion
编辑
我从其他答案中看到,在PHP中可以使用++代替,太好了!
该代码不必要地复杂。有关更简单的算法,请参见en.wikipedia.org/wiki/。